Может ли денормализация моей базы данных таким образом помочь производительности? - PullRequest
1 голос
/ 27 ноября 2011

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

Я могу сделать это двумя способами:

Метод № 1:

Каждый раз, когда пользователь выбирает другого пользователя, я добавляю в таблицу favorites строку, которая выглядит следующим образом (индекс user_favoriting_id):

id | user_favorited_id | user_favoriting_id
-------------------------------------------

Затем, когда они загружают страницу «Мое избранное», я делаю выборку в таблице избранного, чтобы найти все строки, в которых значение user_favoriting_id равно значению текущего зарегистрированного пользователя. Затем я беру user_favorited_ids для построения одного оператора SELECT и поиска соответствующих пользователей из отдельной таблицы пользователей.

Метод № 2:

Каждый раз, когда пользователь выбирает другого пользователя, я обновляю поле «Избранное» в его строке в таблице пользователей, которая выглядит примерно так (хотя и с несколькими полями, индекс равен id):

id | username | password | email | account_status | timestamp | favorites
--------------------------------------------------------------------------

Я СОГЛАСЕН с идентификатором привилегированного пользователя в поле favorites, чтобы в столбце содержалась строка, разделенная запятыми, например:

10,44,67 и т.д ...

Затем для создания страницы «Избранное», как метод № 1, я просто выберу всех избранных пользователей одним нажатием. Эта часть та же самая.

Я знаю, что метод № 1 - нормализованный способ сделать это, и он намного красивее. Но моя забота об этом конкретном проекте - масштабируемость и производительность выше всего.

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

И я вполне уверен, что использование функции разнесения в php для разделения этих значений CSV в методе # 2 не займет почти столько же времени, сколько дополнительные db метода # 1 ищут в таблице favorites, но на всякий случай Я должен спросить:

С точки зрения производительности, какой из этих методов более оптимизирован?

Также, пожалуйста, предположите, что этот сайт будет получать триллион просмотров страниц в день.

Ответы [ 5 ]

1 голос
/ 27 ноября 2011

Вы говорите, что масштабируемость является проблемой. Кажется, это подразумевает, что метод № 2 не будет работать для вас, потому что это ограничивает количество избранных, которые может иметь пользователь. (Например, если у вас миллион пользователей, то у большинства пользователей будут пятизначные идентификаторы. На какой ширине вы хотите указать favorites? Если это VARCHAR(1000), это означает, что разрешено менее 200 избранных. )

Кроме того, действительно ли вы ожидаете, что никогда не захотите узнать, какие пользователи "добавили в избранное" данного пользователя? Ваш метод № 2 может быть О.К. если вы знаете, что вы будете всегда искать предпочтения по "фавориту", а не "фавориту", но в противном случае он полностью развалится. (И даже здесь, это имеет смысл, только если вы не ожидаете найти что-либо значимое о «избранном», кроме его / ее идентификатора пользователя; в противном случае, если вы действительно ищете «избранных», тогда вы в основном делаете всю тяжелую работу JOIN, просто исключив любую возможность для MySQL интеллектуально выполнять JOIN.)

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

1 голос
/ 27 ноября 2011

СОЕДИНЕНИЯ требуют времени, но я бы не стал вносить изменения, пока у вас не появятся какие-либо данные, свидетельствующие о том, что это необходимо.

Нормализация хороша по ряду причин;это не просто учебное занятие.

Объединение идентификаторов в столбец - отвратительное преступление против нормализации.Не делайте этого.

Вы предполагаете, что ваш код работает быстрее, чем вся работа, которая была проделана для оптимизации реляционных баз данных.Это большая ошибка.

Убедитесь, что у вас есть индексы для первичных и внешних ключей, которые участвуют в JOIN.

Профилируйте ваше приложение, если у вас есть реальные проблемы с производительностью;не угадай.

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

0 голосов
/ 28 ноября 2011

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

НЕ используйте шаблон с разделенными запятыми списками идентификаторов.Это просто отстой.

Я сильно подозреваю, что у вас не будет достаточно пользователей на вашем сайте, чтобы это имело значение, поскольку, если вы не являетесь Facebook, у вас вряд ли будет> 1 млн пользователей.Большинство из тех пользователей 1M не выберут никого в качестве своего любимого (потому что большинство из них будут обычными пользователями, которые не используют эту функцию).

Таким образом, вы смотрите на очень маленькую таблицу (скажем, строки 1M)максимум, если ваши пользователи 1М имеют в среднем 1 избранное, хотя большинство вообще не используют эту функцию) с двумя столбцами.Вы можете потенциально улучшить сканирование в innodb, начав с первичного ключа с того, по чему вы чаще всего хотите искать, НО - получите это - вы все равно можете добавить вторичный индекс к другому и получить разумное время поиска (на самом деле, ОЧЕНЬ быстро, как таблица поместится в память на крошечном сервере!)

0 голосов
/ 27 ноября 2011

Насколько я знаю, использование dernomalization в mysql действительно тривиально.но если вы будете использовать что-то вроде не RDBMS, а db, например couchdb или mongoDB, есть весь механизм безопасного манипулирования данными.И это действительно масштабируемая нереляционная база данных будет работать для вас действительно быстрее ..

Единственный метод, который предпочитает оптимизировать веб-приложение, использующее, например, mysql, этодерномализовать таблицу, а затем дать какую-то работу php, и, конечно же, используя HipHop, вы получите там действительно большую оптимизацию, потому что вы загрузили mysql и загрузили php, который с HipHop будет оптимизирован до 50%!

0 голосов
/ 27 ноября 2011

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

Но нет никаких оснований не использовать и другой подход, если нормализованный подход неприемлем для производительности чтения.Часто альтернативный денормализованный подход будет лучше для производительности чтения.Итак, используйте первый как «мастер» для отслеживания данных и обеспечения целостности данных, а затем сохраните денормализованную «копию» данных в другой структуре для доступа для чтения ... Обновите копию с мастеракаждый раз, когда он меняется, (вставляет обновления, удаляет).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...