Правильные индексы базы данных с подзапросом - PullRequest
2 голосов
/ 22 января 2012

ИНФОРМАЦИЯ

В настоящее время у меня есть две таблицы, с которыми я работаю - таблица POST, которая содержит данные для отдельных сообщений, и таблица ИЗБРАННОЕ, которая содержит данные для пользователей, которые решили сохранить избранные сообщения в своем профиле.

Таблицы выглядят так:

POSTS and FAVORITES table

В таблице POSTS для идентификатора есть только первичный ключ, а индексы, которые я установил, отсутствуют. В Избранное у меня есть комбинированный индекс, который я тестировал (postid, deviceid).

Таблица POSTS содержит ок. 10000 записей.

Таблица ИЗБРАННОЕ содержит ок. 4 680 500 записей.

Запрос, который я использую, чтобы получить избранное из определенного deviceid:

SELECT post FROM POSTS 
WHERE id IN 
   (SELECT postid FROM favourites WHERE deviceid="12d4a4a4a4a4a4a");

ПРОБЛЕМА:

При количестве возвращаемых данных и нескольких устройствах, имеющих несколько избранных, запрос может занять до 7-10 секунд на оба сообщения COUNT для определенного устройства и / или SELECT с использованием вышеуказанного запроса и подзапроса. Когда это происходит в часы пик, вы, очевидно, можете представить себе проблемы, которые могут вызвать.

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

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

Любой совет / руководство очень ценится.

Приветствия

Джаред

Ответы [ 4 ]

0 голосов
/ 22 января 2012

В MySQL составные индексы могут использоваться только в том порядке, в котором определены ключи. Так что для индекса (postid, deviceid) вы можете использовать индекс, только если у вас есть postid и вам нужен deviceid. Здесь в вашем запросе вы делаете противоположное - у вас есть константа deviceid и вы хотите соответствующий postid. Таким образом, ваш запрос не использует никаких индексов.

Дополнительная информация о составных индексах mysql .

Вы должны либо добавить индекс deviceid, либо повернуть индекс так, чтобы он был (deviceid, postid).

Кстати, ваша таблица favorites очень похожа на соединительную таблицу. Подумайте, нужен ли вам вообще столбец id.

0 голосов
/ 22 января 2012
SELECT post FROM POSTS 
INNER JOIN favourites ON POSTS.id=favourites.postid 
WHERE favourites.deviceid="12d4a4a4a4a4a4a");

разделить индекс на favourites на 2 индекса, один на deviceid и один на postid

0 голосов
/ 22 января 2012

Несколько вещей, которые вы можете сделать, чтобы улучшить производительность:

  • Разделите device_id на таблицу устройств с суррогатным первичным ключом (int) и некластеризованным индексом в varchar device_id. Таблица избранного должна включать только суррогатный ключ таблицы устройств. Это должно уменьшить таблицу избранного и уменьшить индекс вашей таблицы избранного. Чем меньше индекс и меньше таблица, тем быстрее будет поиск.

  • Ваш индекс таблицы избранного неверен. Не должно быть (post_id, device_id). Это должно быть (device_id, post_id), так как ваш запрос должен искать сначала по device_id. Так как строка вашей таблицы избранного настолько мала, я подвергаю сомнению ценность включения post_id в индекс. Это просто не стоит дополнительного места для возможного незначительного улучшения скорости запросов.

РЕДАКТИРОВАТЬ: вам нужно post_id в индексе, чтобы сохранить уникальность записей (просто убедитесь, что device_id является первым).

0 голосов
/ 22 января 2012

Зачем использовать подзапрос?Вы пробовали объединение?

SELECT post FROM posts INNER JOIN favourites ON posts.id=favourites.postid WHERE deviceid="12d4a4a4a4a4a4a"

Вы не будете использовать (только) свои индексы для получения результатов запроса, поскольку поле post отсутствует в каком-либо индексе.Таким образом, вы можете сэкономить время, сделав один запрос, чтобы получить все совпадающие идентификаторы из posts, а затем секунду, чтобы получить значения post.

Использование EXPLAIN SELECT... также поможет вам оптимизировать этозапрос.Вы пробовали это?

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