2009-02-12 3 views
3

Что я могу сделать для оптимизации этого запроса?оптимизировать SQL-запрос

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

Благодарности

ответ

5

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

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

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

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

насколько я понимаю, ваш 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.> 

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

В зависимости от мощности между элементом и myItems вы можете сделать то же самое или вам придется придерживаться внешнего соединения (но не нужно повторно вводить группу).

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

9

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

1

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

ли ваш Itemid и USERID индексированных столбцов?

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

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

0

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

0

Не можете добавить где положение myTable.userIDFav = 3 или myTable.userIDFav равно нулю к WHERE (item .deleted = 0)?

С уважением
Ливен

0

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

Смежные вопросы