我应该在查询大型表时避免使用ORDER BY吗?

时间:2015-12-03 05:46:28

标签: mysql query-optimization

在我们的应用程序中,我们有一个页面向用户显示一组数据,实际上是其中的一部分。它还允许用户通过自定义字段对其进行排序。所以最后这一切都归结为这样的查询:

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会遇到这样的查询问题吗?那么,我该怎么做 - 根本不使用订单部分?

3 个答案:

答案 0 :(得分:2)

问题'这似乎是你有2个要求(在例子中)

  • active = 1
  • 按名称LIMIT 0,50订购

前者可以通过在active字段上添加索引轻松解决 后者可以通过在name

上添加索引来改进

由于您在同一个查询中同时执行这两项操作,因此您需要将此组合成一个索引,以便您快速解析active值,然后从那里获取前50个name

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

CREATE INDEX idx_test ON myTable (active, name)

(理论上,一如既往,请先购买!)

请记住,虽然没有免费午餐这样的东西;您需要考虑添加索引还有缺点:

  • 索引会使你的INSERT / UPDATE / DELETE语句(略微)变慢,通常效果可以忽略但只有测试会显示
  • 索引将需要de数据库中的额外空间,将其视为位于实际数据旁边的附加(隐藏)特殊表。索引只会保存所需的字段+原始表的PK,这通常比整个表少得多,但对于数百万行而言,数据量很少。它可以加起来。
  • 如果您的查询选择了一个或多个不属于索引的字段,那么系统必须先从索引中获取匹配的PK字段,然后通过以下方式查找实际表中的其他字段PK。这可能仍然(很多)比没有索引时更快,但在做SELECT * FROM ...这样的事情时要记住这一点:你真的需要所有的字段吗?
  • 在示例中,您使用的是activename,但从文字中我可以看出这些可能是“动态的”#39}。在这种情况下,您必须预见各种组合。从实际角度来看,这可能是不可行的,因为每个索引都会带有上述缺点,每次添加索引时,您都会再次将该列表添加到该列表中(累积)。

PS:我使用PK来简化,但在MSSQL中,它实际上是聚集索引的字段,其实际上是相同的。我猜测MySQL的工作方式类似。

答案 1 :(得分:1)

解释您的查询,并检查它是否适用于filesort,

如果Order By没有获得任何索引,或者MYSQL优化器更喜欢避免现有的索引进行排序,那么它将与filesort一起使用。

现在,如果您正在获取文件排序,那么您应该最好避免使用ORDER BY,或者您应该创建适当的索引。

如果数据足够小,它会在内存中执行操作,否则它会在磁盘上运行。

因此您可以尝试更改变量< sort_buffer_size>同样。

答案 2 :(得分:0)

总是权衡,提高订单查询性能的一种方法是设置buffersize,然后通过查询运行订单,即时查询性能

设置sort_buffer_size = 100000; <>

如果这个尺寸进一步增加,那么性能将开始下降