注册
达梦数据库:关于不走索引的各种神话
专栏/龙山溪笔谈/ 文章详情 /

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

myth8860 2020/11/27 2598 3 0
摘要 本文列举了在达梦数据库中,创建好索引后进行查询,但查询过程不走索引的场景,使用者应注意。

案例 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)
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服