一次sql优化的机会,被where条件,索引,优化器这三者的决定关系混淆,借助这个问题整理如下:
1.概念
表T1上有列C1、C2、C3、C4、C5、C6、C7、C8。其中在C1,C2,C3,C4上有索引C1234X。
A.查询语句:Select * From T1 Where C1=5 And C2=4 And C3=7 And C4=2
该语句使用索引C1234X,匹配谓词为C1=5、C2=4、C3=7、C4=2。使用这些谓词可以直接完成定位,无需进行索引页的逐个扫描。
D.查询语句:Select * From T1 Where C2=4 And C3=7 And C1=5
该语句使用索引C1234X,匹配谓词为C1=5、C2=4、C3=7。注意,对应Where子句后面的谓词,优化器会根据索引中列的顺序进行重新排序(查询重写)。
E.查询语句:Select * From T1 Where C1=5 And C2=4 And C4=2 And C6=10
该语句使用索引C1234X,匹配谓词为C1=5、C2=4,筛选谓词为C4=2,C6=10为普通谓词(没有索引与之对应)。可以看到,一旦谓词对应的索引列不连续,那么其后的索引列对应的谓词就只能是筛选谓词了。因为一旦不连续,那么该谓词就不能继续使用树结构进行定位了,只能对下层索引页进行逐个扫描。
F.查询语句:Select * From T1 Where C1=5 And C2=4 And C3>7 And C4=2
该语句使用索引C1234X,匹配谓词为C1=5、C2=4、C3>7,筛选谓词为C4=2。一直到C3都能够使用树结构进行定位,但是C4就不行了,因为C3>7给的只是一个范围,该范围内的下层索引页只能由C4谓词进行逐个扫描筛选了。
表T上有列C1、C2、C3、C4、C5、C6、C7、C8。其中在C1,C2,C3,C4上有索引C1234X;C5、C6上有索引C56X;C7上有唯一索引C7X。
用ACCESSTYPE表示访问类型,ACCESEETYPE=I表示使用索引扫描,ACCESSTYPE=N表示使用带In-list谓词的索引扫描。ACCESSNAME表示使用的索引。MATCHCOLS表示匹配的索引列数。对照上面的规则,不再进行详细解释了。
Select * From T Where C1=5 And C2=7 And C5=8 And C6=13
ACCESEETYPE=I , ACCESSNAME=C56X , MATCHCOLS=2 //至于为什么使用的是索引C56X而不是C1234X,这是由优化器的成本估算结果决定的。
Select * From T Where C1=5 And C2 in(5,6) And (C3=10 or C4=11)
ACCESEETYPE=N , ACCESSNAME=C1234X , MATCHCOLS=2 //"or"操作符连接的谓词会被当作不可索引谓词,因此不是匹配谓词,但是可以作为筛选谓词。
Select * From T Where C1=5 And C2=7 And C7=101
ACCESEETYPE=I , ACCESSNAME=C7X , MATCHCOLS=1 //通常唯一索引会优于普通索引,但也不是绝对的。
Select * From T Where C2=7 And C3=10 And C4=12 And C5=16
ACCESEETYPE=I , ACCESSNAME=C1234X , MATCHCOLS=0 //虽然C1234X上没有匹配谓词,C56X上有,但是优化器认为使用索引C1234X更优。