達夢數據庫:關於不走索引的各種神話

案例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)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章