оптимизировать SQL-запрос - PullRequest
       20

оптимизировать SQL-запрос

3 голосов
/ 12 февраля 2009

Что еще я могу сделать, чтобы оптимизировать этот запрос?

SELECT * FROM
    (SELECT `item`.itemID, COUNT(`votes`.itemID)  AS `votes`,
           `item`.title, `item`.itemTypeID, `item`.
           submitDate, `item`.deleted, `item`.ItemCat,
           `item`.counter, `item`.userID, `users`.name,
           TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' ,
           `myItems`.userID as userIDFav, `myItems`.deleted as myDeleted
      FROM    (votes `votes` RIGHT OUTER JOIN item `item`
                  ON (`votes`.itemID = `item`.itemID))
           INNER JOIN
              users `users`
           ON (`users`.userID = `item`.userID)
    LEFT OUTER JOIN
              myItems `myItems`
           ON (`myItems`.itemID = `item`.itemID)
     WHERE (`item`.deleted = 0)
     GROUP BY `item`.itemID,
              `votes`.itemID,
              `item`.title,
              `item`.itemTypeID,
              `item`.submitDate,
              `item`.deleted,
              `item`.ItemCat,
              `item`.counter,
              `item`.userID,
              `users`.name,
              `myItems`.deleted,
              `myItems`.userID
    ORDER BY `item`.itemID DESC) as myTable
where myTable.userIDFav = 3 or myTable.userIDFav is null
            limit 0, 20 

Я использую MySQL

Спасибо

Ответы [ 6 ]

9 голосов
/ 12 февраля 2009

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

5 голосов
/ 12 февраля 2009

Конечно, как сказал @theomega, посмотрите на план выполнения.

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

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

  • пара внешних объединений (оптимизатору сложно определить используемый индекс)
  • группа
  • много столбцов для группировки по

Насколько я понимаю ваш SQL, этот оператор должен делать большую часть того, что делает ваш:

SELECT `item`.itemID, `item`.title, `item`.itemTypeID, `item`.
       submitDate, `item`.deleted, `item`.ItemCat,
       `item`.counter, `item`.userID, `users`.name,
       TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' 
  FROM    (item `item` INNER JOIN users `users`
       ON (`users`.userID = `item`.userID)

ГДЕ

Конечно, при этом пропускается информация из таблиц, к которым вы присоединились, я бы посоветовал добавить необходимые столбцы с помощью подвыбора:

SELECT `item`.itemID, 
       (SELECT count (itemID)
        FROM votes v
       WHERE v.itemID = 'item'.itemID) as 'votes', <etc.>

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

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

Надеюсь, это поможет.

1 голос
/ 12 февраля 2009

Несколько быстрых полуслучайных мыслей:

Индексируются ли ваши столбцы itemID и userID?

Что произойдет, если вы добавите «EXPLAIN» в начало запроса и запустите его? Использует ли он индексы? Они разумны?

Вам нужно выполнить весь внутренний запрос и отфильтровать его, или вы можете поместить часть where myTable.userIDFav = 3 or myTable.userIDFav is null во внутренний запрос?

0 голосов
/ 13 февраля 2009

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

0 голосов
/ 12 февраля 2009

Не можете ли вы добавить предложение where myTable.userIDFav = 3 или myTable.userIDFav имеет значение от до WHERE (item .deleted = 0) ?

Привет
Ливны

0 голосов
/ 12 февраля 2009

Кажется, у вас слишком много полей в списке Group By, так как одно из них - itemID, я подозреваю, что вы можете использовать внутренний SELECT для предварительной группировки и внешний SELECT, чтобы вернуть набор требуемых полей.

...