Серьезная проблема с производительностью MySQL (соединения, временная таблица, сортировка файлов ....) - PullRequest
3 голосов
/ 01 апреля 2009

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

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

Я не эксперт по MySQL, но из того, что я выяснил, благодаря условию OR в операторе объединения необходимо просмотреть таблицу пользователей целом (в настоящее время +44 000 строк) и создает временную таблицу для этого.

В настоящее время приведенный ниже запрос занимает около двух минут, да, две минуты для завершения. Если я удаляю условие ИЛИ и все после него в операторе соединения, оно выполняется менее чем за полсекунды, поскольку ему нужно только просмотреть около 17 из 44 000 пользовательских строк ( объяснение ftw!) .

В следующем примере, идентификатор пользователя: 9834 , и я пытаюсь получить его / ее собственные нет голосов и присоединиться к информации от пользователя, за которого проголосовали результат.

Есть ли лучший и более быстрый способ сделать этот запрос? Или я должен реструктурировать таблицы? Я серьезно надеюсь, что это можно исправить, изменив запрос, потому что в таблицах уже много пользователей (+44 000) и голосов (+130 000), которые мне нужно будет перенести.

спасибо:)

SELECT *, votes.id as vote_id 
FROM `votes` 
LEFT JOIN users ON (
  (
    votes.user_id_1 = 9834
    AND
    users.uid = votes.user_id_2
  )
  OR
  (
    votes.user_id_2 = 9834
    AND
    users.uid = votes.user_id_1
  )
)
WHERE (
  (
    votes.user_id_1 = 9834
    AND
    votes.vote_1 = 0
  )
  OR
  (
    votes.user_id_2 = 9834
    AND
    votes.vote_2 = 0
  )
)
ORDER BY votes.updated_at DESC
LIMIT 0, 10

Ответы [ 2 ]

6 голосов
/ 01 апреля 2009

Вместо ИЛИ вы можете выполнить СОЮЗ из 2 запросов. Мне известны случаи, когда это происходит на порядок быстрее, по крайней мере, в одной другой СУБД, и я предполагаю, что оптимизатор запросов MySQL может иметь ту же «особенность».

SELECT  whatever
FROM    votes v
        INNER JOIN
                users u
                ON v.user_id_1 = u.uid
WHERE   v.user_id_2 = 9834
AND     v.votes_2 = 0

UNION

SELECT  whatever
FROM    votes v
        INNER JOIN
                users u
                ON v.user_id_2 = u.uid
WHERE   v.user_id_1 = 9834
AND     v.votes_1 = 0

ORDER BY updated_at DESC
0 голосов
/ 02 апреля 2009

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

...