【问题标题】:Simple SQL query but huge table - how to optimize?简单的 SQL 查询但巨大的表 - 如何优化?
【发布时间】:2020-07-30 00:33:07
【问题描述】:

我有一个非常简单的 MySQL 查询:

SELECT target FROM table WHERE goal_id=1 AND year>=2015 AND year<=2020

不过,该表有大约 500 万行。因此,它非常慢(大约 10 秒)。

我可以做些什么来改进?索引有帮助吗?如果有,对哪一列有帮助?

【问题讨论】:

    标签: mysql sql indexing query-optimization where-clause


    【解决方案1】:

    对于此查询,您需要以下索引:

    create index myindex on mytable(year, goal_id, target)
    

    这为您提供了一个覆盖索引:在查询中发挥作用的所有列都是索引的一部分,因此这为数据库提供了一个通过仅查看索引来执行查询的良好机会(没有实际查看数据)。

    索引中列的顺序很重要:前两列对应where谓词,最后一列是select子句中发挥作用的列。

    根据数据的基数,您可能还想尝试反转前两列:

    create index myindex on mytable(goal_id, year, target)
    

    基本想法是您希望将更严格的标准放在首位。

    【讨论】:

    • 先使用goalid
    • @TheImpaler:我正在编辑,而您正在评论...实际上,这取决于数据在列中的分布方式(例如,如果只有两个不同的 goalids 和 year 分布超过 100 个不同的值,您首先需要 year)。 OP 没有分享这些信息。
    • 是否将target 字段包含到索引中会带来一些性能提升?
    • 哦,是的,确实如此。这就是所谓的“覆盖指数”。它可以防止 MySQL 的“双索引查找”问题。不需要,但如果你需要性能,那就去做吧。
    • 太棒了,感谢您的提示!创建索引将查询从 10 秒减少到 0.2 秒
    【解决方案2】:

    yeargoal_idtarget 上的索引:

    ALTER TABLE table ADD INDEX index_name (goal_id, year, target)
    

    正如Rick James 所指出的,goal_id 需要在复合索引中排在第一位,因为它与= 匹配,然后是您的范围列year,然后是您要检索的内容,即target

    【讨论】:

    • 非常感谢您的提示!
    • 没有。将= 列放在首位。这样它只会触及索引中的连续行。各个列的基数无关紧要。
    【解决方案3】:

    规则很简单。首先用= 测试的东西。然后最多做一个“范围”。 (而BETWEEN 在性能上等同于一对等价的不等式。)

    更多讨论:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

    而且,正如 GMB 所指出的那样,扩展索引以使其覆盖会带来另一个提升。所有工作都在索引的 BTree 中完成;无需查看数据的 BTree。所以,按这个顺序

    INDEX(goal_id, year, target)
    

    【讨论】:

      【解决方案4】:

      SELECT target FROM table WHERE goal_id=1 AND year BETWEEN 2015 AND 2020

      您可能会发现通过仅引用一年一次来更快地完成查询。

      【讨论】:

      • 谢谢,我不知道那个查询
      • 没有。 BETWEEN实际上是在解析语句或者优化器的时候变成了另一种格式。见EXPLAIN EXTENDED SELECT ...; SHOW WARNINGS;
      • @hubert 请张贴您的 SHOW CREATE TABLE 表;供我自己更深入的分析(我们都会看到您当前的表和索引结构)。 Rick James,感谢您提供的详细信息以及您对 MySQL 工作原理的更深入了解。
      猜你喜欢
      • 1970-01-01
      • 2010-11-03
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 2010-09-11
      • 1970-01-01
      • 2022-08-14
      • 2017-07-22
      相关资源
      最近更新 更多