达梦数据库:关于不走索引的各种神话

案例1:条件列不是索引的首列

--创建表
CREATE TABLE TAB1(C1 INT,C2 CHAR(1),C3 CHAR(1),C4 INT);
--构造测试数据
INSERT INTO TAB1
SELECT LEVEL C1,CHR(MOD(LEVEL,27)+65) C2,CHR(MOD(LEVEL,27)+65) C3,LEVEL C4
FROM DUAL
CONNECT BY LEVEL<=10000;
COMMIT;
CREATE INDEX IDX_C1_C2 ON TAB1(C1,C2);
EXPLAIN SELECT * FROM TAB1 WHERE  C2='A';

1   #NSET2: [1, 250, 112] 
2     #PRJT2: [1, 250, 112]; exp_num(5), is_atom(FALSE) 
3       #SLCT2: [1, 250, 112]; TAB1.C2 = A
4         #CSCN2: [1, 10000, 112]; INDEX33556684(TAB1)

 

  案例2:条件列上有函数或计算

  

--正常情况
EXPLAIN SELECT * FROM TAB1 WHERE  C1 =123;
1   #NSET2: [0, 1, 112] 
2     #PRJT2: [0, 1, 112]; exp_num(5), is_atom(FALSE) 
3       #BLKUP2: [0, 1, 112]; IDX_C1_C2_C3_TAB1(TAB1)
#SSEK2: [0, 1, 112]; scan_type(ASC), IDX_C1_C2_C3_TAB1(TAB1), scan_range[(123,min,min),(123,max,max))

--条件列上有函数
EXPLAIN SELECT * FROM TAB1 WHERE  abs(C1) =123;
1   #NSET2: [137, 25000, 112] 
2     #PRJT2: [137, 25000, 112]; exp_num(5), is_atom(FALSE) 
3       #SLCT2: [137, 25000, 112]; exp11 = var1
#CSCN2: [137, 1000000, 112]; INDEX33556691(TAB1)

--条件列上有计算EXPLAIN SELECT * FROM TAB1 WHERE  C1-1 =123;
1   #NSET2: [137, 25000, 112] 
2     #PRJT2: [137, 25000, 112]; exp_num(5), is_atom(FALSE) 
3       #SLCT2: [137, 25000, 112]; TAB1.C1-1 = 123
#CSCN2: [137, 1000000, 112]; INDEX33556691(TAB1)

EXPLAIN SELECT * FROM TAB1 WHERE  C1 =123+1
1   #NSET2: [0, 1, 112] 
2     #PRJT2: [0, 1, 112]; exp_num(5), is_atom(FALSE) 
3       #BLKUP2: [0, 1, 112]; IDX_C1_C2_C3_TAB1(TAB1)
4         #SSEK2: [0, 1, 112]; scan_type(ASC), IDX_C1_C2_C3_TAB1(TAB1), scan_range[(123+1,min,min),(123+1,max,max))

 

案例3:存在隐式类型转换

--对条件列C1做了隐式的类型转换,将int类型转换为char类型
EXPLAIN SELECT * FROM TAB1 WHERE  C1='1234567890'
1   #NSET2: [137, 25000, 112] 
2     #PRJT2: [137, 25000, 112]; exp_num(5), is_atom(FALSE) 
3       #SLCT2: [137, 25000, 112]; exp_cast(TAB1.C1) = var1
#CSCN2: [137, 1000000, 112]; INDEX33556691(TAB1)


--后面的常量小于10位,优化器对常量做了类型转换,这时可以走索引
EXPLAIN SELECT * FROM TAB1 WHERE  C1='123456789'
1   #NSET2: [0, 1, 112] 
2     #PRJT2: [0, 1, 112]; exp_num(5), is_atom(FALSE) 
3       #BLKUP2: [0, 1, 112]; IDX_C1_C2_C3_TAB1(TAB1)
#SSEK2: [0, 1, 112]; scan_type(ASC), IDX_C1_C2_C3_TAB1(TAB1), scan_range[(exp_cast(123456789),min,min),(exp_cast(123456789),max,max))

--写SQL的时候数据类型最好匹配,不要让优化器来做这种隐式的类型转换
EXPLAIN SELECT * FROM TAB1 WHERE  C1=1234567890
1   #NSET2: [0, 1, 112] 
2     #PRJT2: [0, 1, 112]; exp_num(5), is_atom(FALSE) 
3       #BLKUP2: [0, 1, 112]; IDX_C1_C2_C3_TAB1(TAB1)
4         #SSEK2: [0, 1, 112]; scan_type(ASC), IDX_C1_C2_C3_TAB1(TAB1), scan_range[(1234567890,min,min),(1234567890,max,max))

 

案例4:如果走索引会更慢

--创建测试表
CREATE TABLE TX(ID INT, NAME VARCHAR(100));
--插入数据
BEGIN
FOR  X IN 1 .. 100000 LOOP
  INSERT INTO TX VALUES(X, 'HELLO');
END LOOP;
COMMIT;
END;
--创建索引 更新统计信息
CREATE INDEX TXL01 ON TX(ID);
SP_INDEX_STAT_INIT(USER,'TXL01');

--返回记录较多 不走索引
EXPLAIN SELECT * FROM TX WHERE ID <50000;
1   #NSET2: [12, 49998, 60] 
2     #PRJT2: [12, 49998, 60]; exp_num(3), is_atom(FALSE) 
3       #SLCT2: [12, 49998, 60]; TX.ID < 50000
#CSCN2: [12, 100000, 60]; INDEX33556697(TX)
--返回记录较少 走索引
EXPLAIN SELECT * FROM TX WHERE ID <500;
1   #NSET2: [8, 498, 60] 
2     #PRJT2: [8, 498, 60]; exp_num(3), is_atom(FALSE) 
3       #BLKUP2: [8, 498, 60]; TXL01(TX)
4         #SSEK2: [8, 498, 60]; scan_type(ASC), TXL01(TX), scan_range(null2,500)

 

案例5:没有更新统计信息

--创建测试表
CREATE TABLE TY(ID INT, NAME VARCHAR(100));
--插入数据
BEGIN
FOR  X IN 1 .. 100000 LOOP
  INSERT INTO TY VALUES(X, 'HELLO');
END LOOP;
COMMIT;
END;
--创建索引 
CREATE INDEX TYL01 ON TY(ID);

--未更新统计信息
EXPLAIN SELECT * FROM TY WHERE ID <500;
1   #NSET2: [12, 5000, 60] 
2     #PRJT2: [12, 5000, 60]; exp_num(3), is_atom(FALSE) 
3       #SLCT2: [12, 5000, 60]; TY.ID < 500
#CSCN2: [12, 100000, 60]; INDEX33556699(TY)

--更新统计信息
SP_INDEX_STAT_INIT(USER,'TYL01');
EXPLAIN SELECT * FROM TY WHERE ID <500;
1   #NSET2: [8, 498, 60] 
2     #PRJT2: [8, 498, 60]; exp_num(3), is_atom(FALSE) 
3       #BLKUP2: [8, 498, 60]; TYL01(TY)
4         #SSEK2: [8, 498, 60]; scan_type(ASC), TYL01(TY), scan_range(null2,500)

 

 

你可能感兴趣的:(性能优化)