Медленный SQL-запрос с использованием Order By - PullRequest
2 голосов
/ 21 марта 2011

Я далёк от гуру 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 и их комбинации.

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

Спасибо

Ответы [ 3 ]

0 голосов
/ 21 марта 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
0 голосов
/ 21 марта 2011

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

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

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

ORDER BY `similars`.app_id = 542 DESC
0 голосов
/ 21 марта 2011

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

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

...