Вопрос

Я работаю над веб-сайтом с простой нормализованной базой данных.

Есть таблица «Страницы» и таблица «Просмотры».Каждый раз при просмотре страницы уникальная запись этого представления записывается в таблицу «Просмотры».

При отображении страницы на сайте я использую простой MySQL COUNT() для подсчета количества просмотров для отображения.

Дизайн базы данных выглядит нормально, за исключением этой проблемы:Я не знаю, как получить 10 самых просматриваемых страниц среди тысяч.

Должен ли я денормализовать таблицу «Страницы», добавив столбец Pages.views для хранения общего количества просмотров каждой страницы?Или есть эффективный способ запроса 10 самых просматриваемых страниц?

Это было полезно?

Решение

   SELECT p.pageid, count(*) as viewcount FROM 
   pages p
   inner join views v on p.pageid = v.pageid
   group by p.pageid
   order by count(*) desc   
   LIMIT 10 OFFSET 0;

Я не могу это проверить, но что-то в этом роде.Я бы не стал сохранять это значение без необходимости из-за ограничений производительности (я только что узнал термин «преждевременная оптимизация», и, похоже, он применим, если вы это сделаете).

Другие советы

Это зависит от уровня информации, которую вы пытаетесь сохранить.Если вы хотите записать, кто и когда смотрел?Тогда отдельная таблица подойдет.В противном случае лучше всего использовать столбец «Просмотры».Кроме того, если вы сохраните отдельный столбец, вы обнаружите, что таблица будет чаще блокироваться, поскольку при каждом просмотре страницы будет пытаться обновить столбец для соответствующей строки.

Select pageid, Count(*) as countCol from Views
group by pageid order by countCol DESC
LIMIT 10 OFFSET 0;

Я бы, вероятно, включил столбец «Просмотры» в таблицу «Страницы».

Мне это кажется вполне разумным нарушением нормализации.Тем более, что я не могу себе представить, чтобы вы удаляли просмотры, чтобы не ожидать, что счетчик выйдет из строя.В этом случае ссылочная целостность не кажется сверхкритической.

Нормализация базы данных — это наиболее эффективный/наименее избыточный способ хранения данных.Это хорошо для обработки транзакций, но часто напрямую противоречит необходимости эффективного повторного получения данных.Проблема обычно решается путем использования производных таблиц (индексов, материализованных представлений, сводных таблиц...) с более доступными предварительно обработанными данными.Модное словечко (немного устаревшее) — «Хранилище данных».

Я думаю, вы хотите сохранить нормализованную таблицу страниц, но иметь дополнительную таблицу с итоговыми значениями.В зависимости от того, насколько свежими должны быть эти подсчеты, вы можете обновить таблицу при обновлении исходной таблицы или использовать фоновое задание для периодического пересчета итогов.

Вы также должны делать это только в том случае, если вы действительно столкнетесь с проблемой производительности, чего не произойдет, если у вас не очень большое количество записей или очень большое количество одновременных обращений.Сохраняйте гибкость кода, чтобы иметь возможность переключаться между наличием таблицы и ее отсутствием.

В этом случае денормализация определенно сработает.Ваша потеря — это дополнительная кладовая, занятая дополнительной колонной.

В качестве альтернативы вы можете настроить запланированное задание для заполнения этой информации каждую ночь, когда у вас низкий трафик, в течение x периода времени.

В этом случае вы потеряете возможность мгновенно узнать количество страниц, если не запустите этот запрос вручную.

Денормализацию определенно можно использовать для повышения производительности.

--Крис

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top