【问题标题】:MySQL queries - defining compound and single indexes across multiple queries. How to prevent the indexes from conflicting and creating slow queries?MySQL 查询 - 跨多个查询定义复合索引和单个索引。如何防止索引冲突和创建慢查询?
【发布时间】:2019-05-24 18:54:06
【问题描述】:

我正在努力找出最适合放置我的索引的列,而添加额外的索引似乎会对查询性能产生不利影响。

例如,我对大约 5m 行的表进行以下查询;

SELECT col1, col2 FROM table WHERE col1 = 'a' AND col2 = 'b' AND col3 = 'c';

在没有索引的情况下运行这个需要 12 秒!

我在所有 3 列上添加了一个复合索引 - table_col1_col2_col3_index;

我的查询现在下降到 2 秒 - 太棒了!

我现在在同一张表上有另一个查询(任何列上都没有索引):

SELECT col1, col2 FROM table WHERE col1 = 'a';

自行运行,查询需要 4 秒 - 仍然很慢!

所以现在我将单列索引添加到 col1 table_col1_index

我的查询减少到 0.2 秒。这很好,但是我现在再次运行原始查询,并注意到它使用的索引与我之前指定的索引相反。原来的查询现在在 6 秒后备份。

我不确定如何确保可以同时优化两个查询。

【问题讨论】:

  • 如果你只有那个原始的多列索引怎么办?只要您按顺序搜索列,MySQL 仍应使用该索引。因此,如果您有一个包含col1col2col3 的多列索引集,并且仅对col1 进行查询,它仍将使用该索引。或者,如果您搜索 col1col2 - 但如果您单独搜索 col2,则不会。
  • 您暗示在某些时候删除第一个复合索引;只是为了确定,你把它加回来了,对吧? MySQL 通常非常擅长选择最佳索引,但如果没有,则可以提示或强制使用特定索引。 official ref
  • 您的第二个查询应该使用第一个索引,性能相当。

标签: mysql sql indexing


【解决方案1】:

您可以创建索引,注意将最常用或选择性的列留在左侧,然后尽可能组织索引,以便在更多查询中使用相同的索引..

此外,您始终可以使用 FORCE(或 IGNORE)https://dev.mysql.com/doc/refman/8.0/en/index-hints.html 打印您认为最适合的索引

SELECT * FROM table1 FORCE INDEX (col3_index)
WHERE col1=1 AND col2=2 AND col3=3;

【讨论】:

    【解决方案2】:
    • 关闭查询缓存,或者做计时时使用SELECT SQL_NO_CACHE ...

    • 每个定时测试运行两次。第一个可能花费额外的时间从磁盘获取数据和/或索引块。第二个时机更适合比较。 (并且更接近“生产”服务器中的方式。)

    • 返回了多少行?这可能会产生影响。第二个查询可能会返回多倍的行数。

    • 请提供SHOW CREATE TABLE -- 可能存在细微问题。 (数据类型、列大小、排序规则、谁知道什么)

    • 请提供EXPLAIN SELECT ... -- 正如所写的那样,您的每个示例都应该说“使用索引”,这意味着索引“覆盖”了查询,这意味着 所有 列在SELECT 中存在INDEX 被使用。

    • 不要使用“索引提示”——虽然它可能有助于今天的查询,但明天可能会更有害。

    • 您的所有示例都将(“应该”)从INDEX(col1, col2, col3) 中受益,按此顺序;我不会添加任何其他人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-11
      • 2011-05-25
      • 1970-01-01
      • 2014-06-29
      • 2011-04-10
      • 2021-12-13
      相关资源
      最近更新 更多