【问题标题】:Even with indices this query is relatively slow. How to speed it up?即使使用索引,此查询也相对较慢。如何加快速度?
【发布时间】:2021-07-31 23:31:15
【问题描述】:

我有一张名为视频的表格。它有比这更多的列,但对于这个例子来说应该足够了。

+----+-------------+------------+----------+--------+
| ID | Title       | Date       | Quality  | Length |
+----+-------------+------------+----------+--------|
|  1 | video title | 2001-01-01 | 720      | 50     |
+----+-------------+------------+----------+--------+

我希望能够按此表中的几乎所有内容进行排序和过滤。因此,我为每个可排序的列创建了一个索引,并为您可以过滤的列创建了一个复合索引。在我想同时排序和过滤之前,它工作得很好。

在这个查询中,它使用了复合索引,一切都很好。查询耗时 0.003 秒

select * 
from videos
where quality = 720
and length = 50
limit 20

这里它使用日期索引。效果很好。查询耗时 0.003 秒

select * 
from videos
order by Date desc
limit 20

这里使用的是日期索引。查询耗时 1.3 秒

select * 
from videos
where quality = 720
and length = 50
order by Date desc
limit 20

所以,显然这是因为它按日期排序,然后检查每一行,直到找到 20 个匹配的行。如果它需要遍历成千上万行直到找到匹配的行,有时会很快,有时会很慢。

但是如何加快速度呢?缓存是这里唯一的解决方案吗?或者还有什么我可以做的吗?

编辑:如果我提示使用复合索引,它仍然很慢。我猜这是因为它仍然需要在逐行遍历它们之前进行排序。

【问题讨论】:

  • 没有。我使用哪个索引并不重要。
  • 你试过“强制索引”而不是“使用索引”吗?
  • 速度差不多。 1.2 秒。问题是,即使使用复合索引,我也会得到很多结果。
  • 您需要向我们展示表和索引定义,以及每个表的行数。也许您的表格定义不佳。也许索引没有正确创建。也许您认为您在该列上没有索引。没有看到表和索引定义,我们无法判断。我们需要行计数,因为这会影响查询计划。如果您知道如何进行EXPLAIN 或获得执行计划,请将结果也放入问题中。

标签: mysql query-optimization


【解决方案1】:

您显示的查询需要以下索引:

ALTER TABLE videos ADD INDEX (quality, length, date)

前两列qualitylength 可以按任意顺序排列,但它们都必须在date 列之前。

记住 MySQL 优化排序的方式:针对 InnoDB 表的查询按索引顺序读取行。如果它读取行的顺序恰好是您在ORDER BY 中请求的顺序,那么它可以简单地跳过对其进行排序所需的任何工作。它按照读取它们的顺序(即索引顺序)返回行。

如果您仅对 (quality, length) 有一个复合索引,则有一个隐式的额外列作为主键。由于您请求了质量和长度的特定值,因此将按主键顺序读取行。 MySQL 不能保证这与date 的顺序相同,因此它必须通过额外的工作对行进行排序。

但是,如果您在索引定义中包含额外的列 date,这就是读取行的顺序,因此它可以优化排序工作。

【讨论】:

  • 感谢这工作。 Nineberry 确实首先回答了,但这是一条评论,所以我会接受这个答案。
猜你喜欢
  • 1970-01-01
  • 2023-04-05
  • 2021-04-17
  • 2016-10-30
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
相关资源
最近更新 更多