使用 Order By 进行慢速 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
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
无论
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
您可以尝试的一件事是将 WHERE 子句移至 JOIN 条件。我认为mysql有时会尝试在使用where子句进行过滤之前进行连接。这只是你可以尝试的事情,我不确定它是否真的有帮助。
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.
由于
FIELD()
正在调用函数,MySql 无法使用索引或排序,来自文档:重写您的
ORDER BY
以不使用任何函数,例如,如果您希望app_id = 542
显示在顶部,您可以编写:Since
FIELD()
is calling a function, MySql cannot use a index or sorting, From the docs:Rewrite your
ORDER BY
to not use any functions, for example if you want the aapp_id = 542
to show up on top you can write: