在组合列或每个组合上唯一创建索引

时间:2020-07-17 03:53:39

标签: mysql sql indexing

在我的情况下,我有以下几列。

a,b,c,d,e,f

-> f is updated time stamp
-> b has cardinality of two distinct elements.
-> c and d columns have maximum distinct elements 10.
-> = queries on columns a, b and like queries on columns c, d and e

我的查询组合如下所示。

a b ORDER BY DESC f
a b c ORDER BY DESC f
a b d ORDER BY DESC f
a b e ORDER BY DESC f

我想知道创建索引的可行选择是什么。

a。我可以一起在(a,b,c,d,e)或(a,b,c,d,e,f)上创建索引吗?

b。将时间戳列f添加到索引是否有帮助?

c。索引中提到的列顺序是否可以提高性能?

示例查询

SELECT * FROM SampleTable T WHERE T.a = 123 and T.b='y' ORDER BY DESC T.f
SELECT * FROM SampleTable T WHERE T.a = 123 and T.b='y' and T.c Like '' ORDER BY DESC T.f
SELECT * FROM SampleTable T WHERE T.a = 123 and T.b='y' and T.d Like '' ORDER BY DESC T.f
SELECT * FROM SampleTable T WHERE T.a = 123 and T.b='y' and T.e Like '' ORDER BY DESC T.f

2 个答案:

答案 0 :(得分:2)

a。我可以一起在(a,b,c,d,e)或(a,b,c,d,e,f)上创建索引吗?

INDEX(a, b, c, d, e, f)将处理需要(a, b, c, d, e)的情况。因此,只做更长的一个。但是-这将完全不会完全处理您的任何示例SELECTs

b。将时间戳列f添加到索引是否有帮助?

是的。例如,WHERE T.a = 123 and T.b='y' ORDER BY DESC T.f喜欢INDEX(a,b),但更喜欢(a,b,f)。但是不是(a,b,c,f)并不比(a,b)好。仅使用最左边的; c在这里。

c。索引中提到的列顺序是否可以提高性能?

这取决于。 WHERE T.a = 123 and T.b='y'INDEX(a,b)(b,a)一样满意。但是,假设两个测试均为=。 (此外,“基数”也没关系。)

AND c赞

AND c = ''相同。但是AND c LIKE 'x%' works like a "range" and 和c类似'%x'cannot use an index for c`。

要最佳地处理所有4个示例查询,您将需要4个索引。但是,以下一个索引可能是一个合理的折衷方案:

INDEX(a,b,f)

阅读此内容;它说明了所有这些,还有更多内容:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

答案 1 :(得分:1)

情况1:此表具有且仅包含以下列,a, b, c, d, e, f

情况2:此表包含更多列

对于情况1,我认为您不需要在(a,b,c,d,e)或(a,b,c,d,e,f)上创建索引,因为:

  1. b和c的基数不太大,因此与完全扫描几乎相同。如果在(a,b,c,d,e)或(a,b,c,d,e,f)上使用索引,则仍需要返回表。
  2. 由于索引的最左前缀,(a,b,c,d,e)和(a,b,c,d,e,f)都无法统计所有查询。

对于情况2,我也不认为您需要创建这两个索引:

  1. 再次以最左边的前缀
  2. 我注意到sql将获得所有列。因此,对于两个索引,mysql需要返回表并获取所有需要的列数据。

那您应该添加什么索引? 我认为那应该取决于您的业务。


如果该表不会被过分更新,并且会执行很多查询,我认为您可以添加服务器不同的索引以提高查询性能。

index on (a b f)
index on (a b c f)
index on (a b d f)
index on (a b e f)

如果查询和更新同时存在,则索引过多。我们需要仔细考虑。我注意到您已经列出了b,c和d的基数,所有三列都有少量不同元素的基数。也许具有更大的不同元素基数。这样,在(a,b,c)或(a,b,d)上添加索引与使用索引几乎相同,然后根据返回表数据进行过滤。 (a,b,e)可能会更有效。

index on (a, b, e)

考虑按f排序,我不确定基数是什么。如果最终查询结果不是太大,则msyql将使用mysql排序缓冲区。因此加f不是必需的。 如果结果太大,也许您可​​以考虑:

index on (a, b, f).

当查询条件为a = xxx and b = yyy order by f时,mysql将不需要对结果进行排序。它只是返回表并读取所有列,然后返回到客户端。

当查询条件类似于a = xxx and b = yyy and c like 'zzz' order by fa = xxx and b = yyy and d like 'zzz' order by fa = xxx and b = yyy and e like 'zzz' order by f时。因为a和b是相等的条件,并且索引类似于(a,b,f),所以当条件为a = xxx and b = yyy时,结果将按f排序。其实,mysql会从innodb一步一步地获取数据,详细步骤如下:

  1. 根据条件a = xxx and b = yyy通过索引(a,b,f)检索第一个主要ID
  2. 返回表并从集群索引中获取所有需要的列
  3. 检查其他查询条件,例如d like 'zzz'。如果匹配,则放入结果集中。如果不匹配,请谨慎。
  4. 重复步骤1、2和3,直到找不到匹配数据。
  5. 将结果返回给客户

注意:工作流仅在查询条件必须包含a和b并且相关条件必须等于条件时才起作用,例如“ a = xxx和b = yyy”。否则,mysql将在其他工作流程中执行,并将使用file或sort_buffer对结果进行排序。

无论如何,以上所有这些分析都是理论上的。最好的方法仍然是对您的环境进行一些测试。无论您创建索引的效率如何,当业务变化时,情况都会变得更糟。