注册
组合索引中列的顺序问题
专栏/金的探索记录/ 文章详情 /

组合索引中列的顺序问题

2021/01/20 2246 2 1
摘要 组合索引中列的顺序对执行计划的影响比较大,本文以具体的 SQL 介绍组合索引中列的顺序对 DM 执行计划的影响。

组合索引中列的顺序对执行计划的影响比较大。下面先简单介绍组合索引的适用场景,后面再根据一个具体的 SQL 说说组合索引中列的顺序对 DM 执行计划的影响。

使用组合索引查询的场景

兹有 Index (A,B,C) ——组合索引多字段是有序的,并且是个完整的BTree 索引。

下面条件可以用该组合索引查询:

A>5 A=5 AND B>6 A=5 AND B=6 AND C=7 A=5 AND B IN (2,3) AND C>5

下面条件将不能用该组合索引查询:

  • B>5 ——查询条件不包含组合索引首列字段
  • B=6 AND C=7 ——查询条件不包含组合索引首列字段

下面条件将能用部分组合索引查询:

  • A>5 AND B=2 ——当范围查询使用第一列,查询条件仅仅能使用第一列
  • A=5 AND B>6 AND C=2 ——范围查询使用第二列,查询条件仅仅能使用前二列

使用组合索引排序的各种场景

兹有组合索引 Index(A,B)。下面条件可以用该组合索引排序:

  • ORDER BY A——首列排序
  • A=5 ORDER BY B——第一列过滤后第二列排序
  • ORDER BY A DESC, B DESC——注意,此时两列以相同顺序排序
  • A>5 ORDER BY A——数据检索和排序都在第一列

下面条件不能用该组合索引排序:

  • ORDER BY B ——排序在索引的第二列
  • A>5 ORDER BY B ——范围查询在第一列,排序在第二列
  • A IN(1,2) ORDER BY B ——理由同上
  • ORDER BY A ASC, B DESC ——注意,此时两列以不同顺序排序

组合索引的执行计划的影响

先看一条查询的 SQL:

SELECT count(*)FROM UCAP_DEPT WHERE DEPT_UNPT_UNID ='00000000000000000000000000000000' OR ( DEPT_BELONGTO = '00000000000000000000000000000000' AND DEPT_TYPE ='2') OR (DEPT_BELONGTO IN (SELECT T.DEPT_UNID FROM UCAP_DEPT T WHERE T.DEPT_BELONGTO ='00000000000000000000000000000000' AND T.DEPT_TYPE ='2' ) );

分析下这条 SQL 该如何建索引,根据 UCAP_DEPT 这个表中的记录数,可以判断通过 DEPT_BELONGTO 能够过滤很多记录,这条 SQL 最好的计划应该是先将以下结果查询出来:

SELECT T.DEPT_UNID FROM UCAP_DEPT T WHERE T.DEPT_BELONGTO ='00000000000000000000000000000000' AND T.DEPT_TYPE ='2'

查询结果出来后,再进行后续查询,先建索引:

create index IDX_UCAP_DEPT_TO_TYPE on ucap_price.UCAP_DEPT(DEPT_BELONGTO.DEPT_TYPE,DEPT_UNID);

收集统计信息:

sp_index_stat_init('UCAP_PRICE','IDX_UCAP_DEPT_TO_TYPE');

看看执行计划:

1.png

可惜不是最优的计划,但是这个计划在并发的情况下速度不会慢的,代价也很小。在目前的版本里面这个计划算是最优的。

  • 再建索引

根据上面的计划,走 NEST LOOPINDEX JOIN2 的话,按照下面的索引顺序建索引是否会好点呢?

create index IDX_UCAP_DEPT_TO_TYPE on ucap_price.UCAP_DEPT(DEPT_TYPE,DEPT_BELONGTO,DEPT_UNID);

收集统计信息:

sp_index_stat_init('UCAP_PRICE','IDX_UCAP_DEPT_TO_TYPE');

此时的执行计划:

2.png

可以看到在第 8 行,一个走的是 NEST LOOP INDEXJOIN2 一个走的是 HASH2 INNER JOIN 我们知道,走 hash 的话对内存等要求比较高,并发下面占用内存比较多。所以这个 a 的索引顺序比较合适。因为目前系统刚上线数据量比较小,后期数据量大的话效果会更明显。并且但从计划上面也可以看出,就目前的数据量来看,a 的索引顺序比b的代价要小,并且实际执行的时间比 b 的也快1被以上(K1 环境)。

Oracle中索引顺序的影响

上面的 SQL 在 Oracle 中测试了下,发现 Oracle 中索引的顺序没有影响,两种索引计划一样:

3.png

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服