Оптимизация Mysql Query - PullRequest
       6

Оптимизация Mysql Query

2 голосов
/ 28 октября 2009

Какова общая «лучшая практика» для этого типа функциональности.

У меня есть таблица пользователей, таблица опросов и таблица ответов на веб-сайт. Я хочу загрузить страницу, которая загружает опрос, на который пользователь еще не ответил.

Какой самый эффективный и «лучший» способ добиться этого.

То, что я пробовал, кажется медленным / неоптимальным:

Запрос с вложенными выборками с использованием NOT IN

SELECT p.id
FROM poll p
WHERE p.id NOT IN (
    SELECT r.pollID
    FROM responses r
    WHERE r.username = 'someuser'
)

Запрос, который использует левые соединения

LEFT JOIN  responses ON ( polls.id = responses.pollID
AND responses.username =  'someuser' ) 
WHERE
responses.username IS NULL

Оба эти решения, похоже, очень плохо масштабируются.

Другие предложения? Открыто для чего-либо вне коробки. (Т.е. решения, которые не ограничиваются только различными типами запросов mysql)

Ответы [ 4 ]

3 голосов
/ 28 октября 2009

Оба эти запроса одинаково эффективны, если у вас есть составной индекс на responses (pollID, username)

Если ваши запросы медленные, это, скорее всего, означает, что у вас нет этого индекса.

LEFT JOIN в сочетании с IS NULL в столбце, отличном от NULL, оптимизируется на MySQL, поэтому он возвращает строку, как только обнаруживает, что в правом столбце нет соответствующего значения.

Вы можете увидеть его в EXPLAIN как Not exists в столбце Extra.

NOT IN также оптимизирован, вы можете увидеть это как <not exists> в предупреждающем сообщении EXPLAIN EXTENDED.

Смотрите эту запись в моем блоге для более подробной информации:

0 голосов
/ 28 октября 2009

Левое соединение должно отлично работать, если вы дадите responses составной ключ на pollID и username.

Хотя несколько печально, что вы используете имя пользователя в качестве ключа, а не числовой идентификатор пользователя.

0 голосов
/ 28 октября 2009

Решение № 1:

Как вам подходит прямое соединение слева?

LEFT JOIN  responses ON ( polls.id = responses.pollID
AND responses.username =  'someuser' ) 

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

Решение № 2:

Убедитесь, что ваши показатели в порядке. У вас должен быть индекс ann в имени пользователя (или ID опроса + имя пользователя) в ответах.

0 голосов
/ 28 октября 2009

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

LEFT JOIN  responses ON ( polls.id = responses.pollID) 
WHERE
responses.username = 'someuser'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...