【问题标题】:Creating an INDEX to improve slow execution time caused by ORDER BY创建 INDEX 以改善由 ORDER BY 导致的执行时间缓慢
【发布时间】:2018-01-18 12:42:20
【问题描述】:

我在 PHP 函数中有以下查询。这会根据多种因素被调用多次,但即使只执行 1 次也需要很长时间。

SELECT  `date` as dateTo
FROM    table_name tbl
WHERE    `colA` = 223 and `colB` <> 1
ORDER BY `date` DESC
LIMIT 1

数据库表有大约 200 万条记录,ORDER BY 正在减慢执行时间。

在这种情况下我能拥有的最好的INDEX 是什么?

date 上的索引是否只会有益,还是我必须包含 colAcolB

-----

我最终使用了这个查询,

SELECT  `ColA`,`date`, `ColB`
FROM  atm_status_log
WHERE  `ColA` = 223
HAVING  `ColB` <> 1
ORDER BY `date` DESC
LIMIT 1;

还有这个INDEXINDEX(colA, colB, date)

【问题讨论】:

  • 目前存在什么索引?
  • 最佳索引是INDEX(date, colA, colB) 上的多列索引,请注意索引应按照我所说的方式对列进行排序。
  • 有多少行会被选中并需要排序?
  • @RiggsFolly 该表按降序排列,因此所有记录都已排序。
  • @RaymondNijland 如果您添加评论作为答案,我会选择它。

标签: php mysql sql indexing phpmyadmin


【解决方案1】:

colB 中有多少个不同的值?如果它只能有01,则将过滤器更改为

colB = 0

并添加这个

INDEX(colA, colB, date)

date 必须在最后,但 A 和 B 可以是任意顺序。)只有这样,所有过滤和ORDER BY 才能由INDEX 处理。

如果 colB 的值超过 2 个,那么让我们稍微改进一下 Gordon 的解决方案:

SELECT  `date` as dateTo
    FROM  table_name tbl
    WHERE  `colA` = 223
      AND   colB <> 1
    ORDER BY  `date` DESC;

使用INDEX(colA, colB, date),列完全按照该顺序排列。该索引将是一个“覆盖”索引。

【讨论】:

  • HAVING 必须在ORDER BY 之前。在这种情况下,索引会是 INDEX(colA, colB, date) 吗?
  • 索引有效(INDEX(colA, colB, date))而且速度更快。谢谢。
  • 我的错。修正了我的答案。然后,HAVING 并不比WHERE 好(而且可能更差),所以将 colB 测试折叠成 WHERE
【解决方案2】:

您必须在日期、colA、colB 上添加索引。 请记住该索引的顺序很重要。

ALTER TABLE table_name ADD KEY index_name (date, colA, colB); 

【讨论】:

  • 以列作为范围比较或在ORDER BY 中使用的复合索引几乎总是次优的。从date 开始,优化器可以使用ORDER BY 的索引,但不能用于过滤colA。一个缓解因素是它是一个“覆盖索引”,因为它包含查询所需的所有列。
【解决方案3】:

这是您的查询:

SELECT `date` as dateTo
FROM table_name tbl
WHERE `colA` = 223 and `colB` <> 1
ORDER BY `date` DESC
LIMIT 1

一种索引方法是table_name(colA, colB, date)。这是查询的覆盖索引。但是,它不会消除排序。

可以试试这个方法:

SELECT dateTo
FROM (SELECT `date` as dateTo, colB
      FROM table_name tbl
      WHERE `colA` = 223 
      ORDER BY `date` DESC
     ) t
WHERE `colB` <> 1;

子查询应该能够使用table_name(colA, date) 上的查询。它需要具体化整个结果集,但是选择colB &lt;&gt; 1 应该很快。我对这种方法并不感兴趣,因为它假定子查询在被外部查询读取时保持有序——但在 MySQL 中确实如此。

【讨论】:

  • 第二种方法确实提高了执行时间,谢谢,我也会尝试索引。
【解决方案4】:

您必须为 colA 和 colB 添加索引。这将解决问题。

【讨论】:

    猜你喜欢
    • 2018-04-02
    • 2019-10-26
    • 2010-10-16
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    • 2021-04-22
    • 2020-05-15
    • 2021-06-23
    相关资源
    最近更新 更多