使用 Order By 进行慢速 SQL 查询

发布于 2024-10-24 02:46:38 字数 2508 浏览 1 评论 0原文

我离 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

order by 使其比没有 order by 慢 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 以及这些索引的组合的所有索引组合。

有什么技巧或窍门吗?

谢谢

I am far from a SQL guru and I am trying to execute:

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

The order by makes it 20x slower than without the order by.

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

Gives me :


+----+-------------+----------+-------------+-------------------------------------------------------------------+-----------------------------------+---------+------+-------+----------+----------------------------------------------------------------------------------------------+
| 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                                                               |
+----+-------------+----------+-------------+-------------------------------------------------------------------+-----------------------------------+---------+------+-------+----------+----------------------------------------------------------------------------------------------+

I have tried all combinations of indexes on app_id, similar_app_id and composites of those.

Any tips or tricks?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

故事↓在人 2024-10-31 02:46:38

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

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

regardless of LIMIT sorting by not indexed field - in your case your make calculation on value to sort would always take longer...

I would skip deduction 542 for ordering and add index for app_id

计㈡愣 2024-10-31 02:46:38

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

One thing you could try is moving the WHERE clause into the JOIN condition. I think mysql will sometimes try to do the join before filtering using the where clause. This is just something you can try and I'm not sure if it will actually help at all.

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
空心↖ 2024-10-31 02:46:38

由于 FIELD() 正在调用函数,MySql 无法使用索引或排序,来自文档

在某些情况下,MySQL无法使用
索引来解析 ORDER BY...
将 ORDER BY 与表达式一起使用:
包括除关键字之外的术语
列名

重写您的 ORDER BY 以不使用任何函数,例如,如果您希望 app_id = 542 显示在顶部,您可以编写:

ORDER BY `similars`.app_id = 542 DESC

Since FIELD() is calling a function, MySql cannot use a index or sorting, From the docs:

In some cases, MySQL cannot use
indexes to resolve the ORDER BY... You
use ORDER BY with an expression that
includes terms other than the key
column name

Rewrite your ORDER BY to not use any functions, for example if you want the a app_id = 542 to show up on top you can write:

ORDER BY `similars`.app_id = 542 DESC
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文