我应该避免在查询大表时使用 ORDER BY 吗?
Posted
技术标签:
【中文标题】我应该避免在查询大表时使用 ORDER BY 吗?【英文标题】:Should I avoid ORDER BY in queries for large tables? 【发布时间】:2015-12-03 05:46:28 【问题描述】:在我们的应用程序中,我们有一个页面向用户显示一组数据,实际上是其中的一部分。它还允许用户通过自定义字段对其进行排序。所以最后一切都归结为这样的查询:
SELECT name, info, description FROM mytable
WHERE active = 1 -- Some filtering by indexed column
ORDER BY name LIMIT 0,50; -- Just a part of it
只要表的大小相对较小(仅在我们部门本地使用),这工作得很好。但是现在我们必须扩展这个应用程序。让我们假设,该表有大约一百万条记录(我们预计这很快就会发生)。订购会发生什么?我是否理解正确,为了执行此查询,mysql 每次都必须对一百万条记录进行排序并给出其中的一部分?这似乎是一个非常耗费资源的操作。
我的想法只是关闭该功能并且不要让用户选择他们的自定义排序(也许只是过滤),以便顺序是自然的(按 id 降序排列,我相信索引可以处理那个)。
或者有没有办法让这个查询在排序时工作得更快?
更新:
这是我从官方 MySQL developer page 中读到的内容。
在某些情况下,MySQL 无法使用索引来解析 ORDER BY, 尽管它仍然使用索引来查找与 WHERE 匹配的行 条款。这些案例包括:
....
用于的密钥 获取的行与 ORDER BY 中使用的不同:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
所以是的,看起来 mysql 会遇到这样的查询问题?那么,我该怎么办 - 根本不使用订单部分?
【问题讨论】:
如果您在name
列上有索引,那么我不认为排序是一件特别糟糕的事情。
【参考方案1】:
这里的“问题”似乎是您有 2 个要求(在示例中)
活动 = 1 按名称订购 LIMIT 0, 50您可以通过在active
字段上添加索引来轻松解决前者
后者可以通过在name
上添加索引来改进
由于您在同一查询中执行这两项操作,因此您需要将其组合到一个索引中,以便您快速解析 active
值,然后从那里获取前 50 个 name
s。
因此,我想这样的事情会帮助你:
CREATE INDEX idx_test ON myTable (active, name)
(理论上,一如既往,在购买之前先试一试!)
请记住,没有免费的午餐。您需要考虑添加索引也有缺点:
索引会使您的 INSERT/UPDATE/DELETE 语句(稍微)变慢,通常影响可以忽略不计,但只有测试会显示 索引将需要数据库中的额外空间,将其视为位于实际数据旁边的附加(隐藏)特殊表。索引将只保存所需的字段 + 原始表的 PK,这通常比整个表的数据少得多,但对于“数百万行”,它可以加起来。 如果您的查询选择了一个或多个不属于索引的字段,则系统必须先从索引中获取匹配的 PK 字段,然后通过PK。这可能仍然比没有索引时快(很多),但在执行SELECT * FROM ...
之类的操作时请记住这一点:您真的需要所有字段吗?
在示例中,您使用了active
和name
,但从文本中我了解到这些可能是“动态的”,在这种情况下,您必须预见各种组合。从实际角度来看,这可能不可行,因为每个索引都会带来上述缺点,并且每次添加索引时,您都会再次将 supra 添加到该列表中(累积)。
PS:为简单起见,我使用PK
,但在 MSSQL 中,它实际上是聚集索引的字段,通常是相同的。我猜 MySQL 的工作原理类似。
【讨论】:
【参考方案2】:解释您的查询,并检查它是否适用于文件排序,
如果 Order By 没有得到任何索引,或者如果 MYSQL 优化器更喜欢避免现有索引进行排序,则使用 filesort。
现在,如果您要进行文件排序,那么您最好避免使用 ORDER BY 或创建适当的索引。
如果数据足够小,它会在内存中执行操作,否则它会在磁盘上进行。
所以您也可以尝试更改变量
【讨论】:
【参考方案3】:总是有权衡,提高顺序查询性能的一种方法是设置缓冲区大小,然后按查询运行顺序查询,从而提高查询性能
设置 sort_buffer_size=100000;
如果这个大小进一步增加,那么性能将开始下降
【讨论】:
设置 sort_buffer_size=100000; 选择 orderby 查询 在我看来过滤索引会对排序索引有问题,我在更新中写过。由于过滤对我来说更重要,也许我不应该提供排序选项?以上是关于我应该避免在查询大表时使用 ORDER BY 吗?的主要内容,如果未能解决你的问题,请参考以下文章
我可以重写这个 SQL 查询以避免“ORDER BY 子句无效”吗
带有“Order Each by”子句的 Google BigQuery 大表(105M 记录)产生“资源超出查询执行”错误