提问人:Andrew G. Johnson 提问时间:1/15/2009 最后编辑:MachavityAndrew G. Johnson 更新时间:8/17/2017 访问量:2271
将 ORDER BY 子句添加到 MySQL 查询使其在 ~30 秒内返回,高于 ~0.5 秒
Adding ORDER BY clause to MySQL query makes it return in ~30 seconds, up from ~0.5
问:
所以我有这个查询,它相对较快,为 ~0.5 秒,但是当我添加 ORDER BY 子句时,它会跳到近 30 秒。
原始查询:(在 ~0.5 秒内返回)
SELECT table1.*,table2.* FROM table1 LEFT OUTER JOIN table2 ON table1.column2=table2.column3 WHERE table1.column1='value' LIMIT 4
使用 ORDER BY: 进行查询(在 ~30 秒内返回)
SELECT table1.*,table2.* FROM table1 LEFT OUTER JOIN table2 ON table1.column2=table2.column3 WHERE table1.column1='value' ORDER BY table1.column4 DESC LIMIT 4
注意:我向 ORDER BY 正在使用的列添加了索引,但它没有更改任何内容。
关于是什么原因导致这种情况的任何想法?
答:
这需要更长的时间,因为查询不能只选取它找到的前 4 个项目。它必须对整个列表进行排序,然后从中选择前 4 名。
通过添加包含 table1{column4, ...} 的索引来解决此问题。如果您只需要表 1 中的几列(而且它们很窄),我会将它们全部添加到索引中(覆盖索引)。
如果索引正确,SQL 引擎只能提取所需的前四列,而不是整个集合。
如果您确实有索引,但它没有帮助,请使用 EXPLAIN 运行查询以查看执行计划的外观(好提示,@IronGoofy):
EXPLAIN
SELECT table1.*,table2.*
FROM table1
LEFT OUTER JOIN table2 ON table1.column2=table2.column3
WHERE table1.column1='value' ORDER BY table1.column4 DESC LIMIT 4
您如何运行查询?
某些工具通常只检索前 100 条左右的记录,并根据需要下拉更多记录。
添加 ORDER BY 会强制工具检索整个数据集。
如果您使用的是 MySql 浏览器,请尝试在不使用 ORDER BY 的情况下运行,然后使用 CTRL-END 滚动到数据网格的底部。这需要多长时间?
table1.column1 是否已编入索引?如果是,则查询优化器将使用该索引从 table1 中选择初始行集,因为它在最坏的情况下是索引范围扫描(非常快)。
如果此查询是频繁运行的查询,则可以通过编制索引 (column1,column4) 来获得所需的性能。我不太了解MySQL,但是使用Oracle,您可以通过索引(column1,column4,column2)来进一步提高性能,这将使优化器从索引中完成所有工作,而不是完全接触表数据。
但是,添加索引是一种权衡:它将增加每次插入(或更新索引列)所花费的时间,使数据库变大,并且由于稀缺的内存资源(即缓冲区缓存)被分配给新索引,可能会导致整体速度变慢。
评论
同意迈克尔的解释,+1。
至于索引没有区别,请查看执行计划(不确定如何在MySQL中执行此操作 - 也许有人可以编辑它?同样,我同意 Michael 的观点,这应该会让事情变得更快(只要 column4 是“选择性的”)。
@kogus:将整个结果集检索到客户端与对结果集进行排序不同,排序应该在服务器上进行,而不需要通过网络传输所有结果
尝试运行 explain:
EXPLAIN SELECT table1.*,table2.* FROM table1 LEFT OUTER JOIN table2 ON table1.column2=table2.column3 WHERE table1.column1='value' ORDER BY table1.column4 DESC LIMIT 4
这可能会告诉你MySQL正在做一个文件排序。你能在(column1, column4)上放一个索引吗?
你能说说更多关于你的模型的信息吗?您使用的是哪些索引?你能展示一些解释输出吗?字段使用哪种类型?
同意迈克尔提到的索引内容。
此外,在MySQL中,您可以通过检查查询前面的EXPLAIN结果来了解查询的性能,例如
EXPLAIN SELECT * FROM foo_tbl WHERE foobar = 'foo'
将帮助您更好地设计查询,并适当地编制索引。阅读 EXPLAIN 语法和使用 EXPLAIN 优化查询。
评论