我应该避免在查询大表时使用 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 个 names。

因此,我想这样的事情会帮助你:

CREATE INDEX idx_test ON myTable (active, name)

(理论上,一如既往,在购买之前先试一试!)

请记住,没有免费的午餐。您需要考虑添加索引也有缺点:

索引会使您的 INSERT/UPDATE/DELETE 语句(稍微)变慢,通常影响可以忽略不计,但只有测试会显示 索引将需要数据库中的额外空间,将其视为位于实际数据旁边的附加(隐藏)特殊表。索引将只保存所需的字段 + 原始表的 PK,这通常比整个表的数据少得多,但对于“数百万行”,它可以加起来。 如果您的查询选择了一个或多个不属于索引的字段,则系统必须先从索引中获取匹配的 PK 字段,然后通过PK。这可能仍然比没有索引时快(很多),但在执行SELECT * FROM ... 之类的操作时请记住这一点:您真的需要所有字段吗? 在示例中,您使用了activename,但从文本中我了解到这些可能是“动态的”,在这种情况下,您必须预见各种组合。从实际角度来看,这可能不可行,因为每个索引都会带来上述缺点,并且每次添加索引时,您都会再次将 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 记录)产生“资源超出查询执行”错误

在数据库查询中order by 后面可以给表达式吗?

查询失败并出现错误 RESOURCE_EXHAUSTED (ORDER BY without ORDER BY)

我需要在 ORDER BY 字段上添加索引吗?

我可以在 SQL 中使用 UNION 子句的查询中添加 ORDER BY 子句吗?