使用Order By进行慢速SQL查询

时间:2011-03-21 01:57:49

标签: mysql sql-order-by explain

我远离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 :(得分:0)

无论LIMIT按索引字段排序 - 在您的情况下,您对排序值的计算总是需要更长的时间......

我会跳过扣除542 进行排序并为app_id添加索引

答案 1 :(得分:0)

您可以尝试的一件事是将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

答案 2 :(得分:0)

由于FIELD()正在调用函数,MySql无法使用索引或排序From the docs

  

在某些情况下,MySQL无法使用   索引来解决ORDER BY ...你   使用ORDER BY表达式   包括除密钥以外的条款   列名

重写您的ORDER BY不使用任何功能,例如,如果您希望a app_id = 542显示在最上面,您可以写:

ORDER BY `similars`.app_id = 542 DESC