Медленный SQL-запрос с использованием упорядочения по

Я далек от гуру SQL и пытаюсь выполнить:

SELECT `apps`.* FROM `apps` 
 INNER JOIN `similars` 
 ON (`apps`.id = `similars`.similar_app_id OR `apps`.id = `similars`.app_id) 
WHERE (`similars`.app_id = 542 
 OR `similars`.similar_app_id = 542) 
 AND apps.id <> 542 
ORDER BY field(`similars`.app_id, 542) desc LIMIT 6

Порядок по делает его в 20 раз медленнее, чем без упорядочения по.

explain extended 
SELECT DISTINCT `apps`.* 
  FROM `apps` 
  INNER JOIN `similars` 
    ON (`apps`.id = `similars`.similar_app_id 
    OR `apps`.id = `similars`.app_id) 
  WHERE (`similars`.app_id = 542 
    OR `similars`.similar_app_id = 542) AND apps.id <> 542 
  ORDER BY `similars`.app_id - 542 desc

Дает мне :


+----+-------------+----------+-------------+-------------------------------------------------------------------+-----------------------------------+---------+------+-------+----------+----------------------------------------------------------------------------------------------+
| id | select_type | table    | type        | possible_keys                                                     | key                               | key_len | ref  | rows  | filtered | Extra                                                                                        |
+----+-------------+----------+-------------+-------------------------------------------------------------------+-----------------------------------+---------+------+-------+----------+----------------------------------------------------------------------------------------------+
|  1 | SIMPLE      | similars | index_merge | index_app_id_and_similar_app_id,index_app_id,index_similar_app_id | index_app_id,index_similar_app_id | 5,5     | NULL |   241 |   100.00 | Using union(index_app_id,index_similar_app_id); Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | apps     | range       | PRIMARY                                                           | PRIMARY                           | 4       | NULL | 21493 |   100.00 | Using where; Using join buffer                                                               |
+----+-------------+----------+-------------+-------------------------------------------------------------------+-----------------------------------+---------+------+-------+----------+----------------------------------------------------------------------------------------------+

Я пробовал все комбинации индексов app_id, similar_app_id и их составные части.

Есть какие-нибудь советы или хитрости?

Спасибо


person Stuart    schedule 21.03.2011    source источник
comment
Для чего вы используете функцию field() в первом запросе?   -  person dcrosta    schedule 21.03.2011


Ответы (3)


независимо от LIMIT сортировки по неиндексированному полю - в вашем случае расчет значения для сортировки всегда занимает больше времени ...

Я бы пропустил вычет 542 за заказ и добавил индекс для app_id

person bensiu    schedule 21.03.2011
comment
Привет, Бенсиу, спасибо за ответ, к сожалению, мне нужен заказ, иначе он работает быстро :) У меня есть индекс по app_id (index_app_id в объяснении) - person Stuart; 21.03.2011

Вы можете попробовать переместить предложение WHERE в условие JOIN. Я думаю, что mysql иногда пытается выполнить соединение перед фильтрацией с использованием предложения where. Это просто то, что вы можете попробовать, и я не уверен, что это вообще поможет.

SELECT `apps`.* FROM `apps` 
 INNER JOIN `similars` 
 ON (`apps`.id = `similars`.similar_app_id OR `apps`.id = `similars`.app_id) 
  AND (
       (`similars`.app_id = 542 OR `similars`.similar_app_id = 542) 
       AND apps.id <> 542
  ) 
ORDER BY field(`similars`.app_id, 542) desc LIMIT 6
person Joe Phillips    schedule 21.03.2011
comment
Привет, Джо, спасибо за ответ! Вы имеете в виду сделать WHERE AND на соединении? Если так, то я пробовал и кажется примерно то же самое: | - person Stuart; 21.03.2011
comment
Спасибо, Джо, это ускоряет работу в два раза, я посмотрю, смогу ли я настроить его дальше - person Stuart; 21.03.2011

Поскольку FIELD() вызывает функцию, MySql не может использовать индекс или сортировку, Из документов:

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

Перепишите свой ORDER BY, чтобы не использовать какие-либо функции, например, если вы хотите, чтобы app_id = 542 отображался сверху, вы можете написать:

ORDER BY `similars`.app_id = 542 DESC
person The Scrum Meister    schedule 21.03.2011
comment
к сожалению, не помогает :( - person Stuart; 21.03.2011