提前說明:
1.TR 表示隨機I/O查找(假設爲10ms)
2.TS 表示順序I/O查找(0.01ms)
3.TR查詢的速度遠遠小於TS
4.一次的查詢,最少一次隨機I/O
5.通過索引查詢,如果無法滿足覆蓋索引條件,需要進行一次回表查詢(隨機I/O)
6.以下都不考慮有緩存的情況
7.下面的僅供參考,如有問題,歡迎留言指出。
設計索引時,一次查詢需要考慮的問題:
1.最好輸入,即執行查詢限定條件,比如limit 20, 索引前20條即可滿足查詢條件
2.最壞輸入,索引無法滿足查詢條件或者需要掃描整個索引
栗子:
1.非聚簇索引且非覆蓋索引
SQL1:SELCT A,B,C,D,F,G FROM TEST WHERE A = A1 AND B=B1 LIMIT 20
索引(A,B) 非聚簇索引
數據量100W, A的過濾因子 1% ,B的過濾因子10% (A,B)共過濾至1000條數據,其中每10條有一個符合B條件的數據。
最壞輸入(符合條件的只有19條)
索引(A,B) TR=1 TS = 1000
回表:TR=19 TS = 0
拉取數據成本:19*0.1ms
總成本:TR(20*10ms) + TS(1000*0.01ms) + 拉取成本(19*0.1ms) = 211ms
最好輸入(直接能找到20條數據)
索引(A,B) TR=1 TS=20
回表:TR=20 TS=0
拉取數據成本:20*0.1ms
總成本: 拉取成本(20*0.1ms) + TR(21*10ms) + TS(20*0.01) = 212ms
(A,B)索引對於SQL1查詢成本 在 200ms 左右
2.符合覆蓋索引且非聚簇索引
SQL2:SELCT A,B FROM TEST WHERE A = A1 AND B=B1 LIMIT 20
索引(A,B) 非聚簇索引
數據量100W, A的過濾因子 1% ,B的過濾因子10%
上述是一個覆蓋索引的查詢方式,會減少回表查詢
最壞輸入(只有19條服務):
索引(A,B):TR=1 TS= 10%*1%*100W = 1000
回表:TR=0 TS = 0
拉取數據成本: 19*0.1ms
總成本:TR(10ms) + 拉取成本(2ms) + TS(10ms) = 22m
最好輸入(直接能找到20條數據)
索引(A,B) :TR=1 TS=20
回表:TR=0 TS=0
拉取數據成本:20*0.1ms
總成本:拉取成本(20*0.1ms) + TR(1*10ms) + TS(20*0.01) = 12ms
(A,B)索引對於SQL2查詢成本在 12ms-22MS 這個範圍
3.對於聚簇索引的查詢,由於聚簇索引包含的了行數據,和覆蓋索引的計算方式基本一致。
4.where字句中,包含非索引過濾
SQL4:SELCT A,B,C,D,F,G FROM TEST WHERE A = A1 AND B=B1 AND C=C1 LIMIT 20
索引(A,B)
數據量100W, A的過濾因子 1% ,B的過濾因子10% C 過濾因子10%(1000符合(A,B),C每10行數據有一個符合要求的)
最壞輸入(符合A,B 但都不符合C):
(A,B) TR=1 TS=1000
回表: TR=1000 TS = 0
拉取數據成本: 0*0.1ms
總成本 TR(1001*10ms) + 拉取成本(0) + TS(1000*0.01ms) = 10s
最好輸入:
數據量100W, A的過濾因子 1% ,B的過濾因子10%
(A,B) TR=1 TS= 20*10
回表:TR=20*10 TS = 0
拉取數據成本: 20*0.1ms
總成本 TR(201*10ms) + 拉取成本(0.2ms) + TS(200*0.01ms) = 2s
(A,B)索引對於SQL4查詢成本在 2s-10s 這個範圍
5.無索引情況下
最差輸入(整個表無法滿足條件)
表: TR=1 TS=100W
拉取成本: 0-20*0.1ms
處理成本 100W*0.01ms = 10 s(假設CPU處理一條數據的時間是0.01ms)
總成本 TR(1*10ms) + TS(100W*0.01ms) + 拉取成本(20*0.1ms) +處理成本(100W*0.01ms)= 10ms+1000ms+2ms+1000ms=20s
最好輸入,前20條就找到
表 TR=1 TS=20
拉取成本 20*0.1ms
處理成本 20*0.01ms
總成本: TR(1*10ms)+處理成本(20*0.01ms) + 拉取成本(2ms)+TS(20*0.01ms) = 12 ms
成本在12ms-20s 之間
總結:
1.在進行索引設計時,要儘量讓查詢減少回表,減少隨機I/O
2.要根據數據量、數據分佈的均勻程度、最好輸入、最壞輸入等因素來評估一個索引的效率。