索引總結

埃裡克拓荒發表於2019-03-29
                        這是資料庫索引相關內容的最後一篇
複製程式碼

對於單表,我們知道了如何設計《最佳索引》;

但是現實中,往往比較複雜,有聯合查詢、巢狀查詢、子查詢等等;我們從以下幾方面展開

  1. 對優化器來說難的謂詞
  2. 跨表查詢
  3. 設計出色索引的步驟

1. 對優化器來說難的謂詞

我們來猜一猜,優化器比較難處理的謂詞可能有哪些?

肯定要排除AND,這足夠簡單;大於/小於呢,單純來看也還行;between and呢;有範圍,應該能接受,那還有什麼?
比如Or,這明顯對優化器有點難了,為什麼,因為它是不滿足A,還得看B,等根據查詢結果來進行判斷需不需要看B;
還有LIKE, 如果LIKE以%開頭,那麼無疑給查詢帶來了難度;
複製程式碼

所以呢,難的謂詞有什麼?

對,就是or、like、in這些,沒有辦法通過簡單的掃描得出結論的,不建議在這些列建立索引。
複製程式碼

這些謂詞,我們有個統一的稱呼,稱呼他們為非布林謂詞。那麼相反,
簡單直接的謂詞就是布林謂詞,就是好的謂詞,可以建立索引

2. 跨表查詢

跨表查詢總結起來就是自個表的部分,以及連線處.

1.連線處是否在索引中很重要
2.就算每個單表都是最佳索引,但是如果有大量隨機IO,仍然會導致查詢慢

select CNO, CNAME FROM TABLE1 WHERE CTYPE = 1;
select DNAME FROM TABLE2 WHERE DNO = CNO AND DCOM = 2;

對於TABLE1,最佳索引為(CTYPE, CNO, CNAME);
對於TABLE2,最佳索引為(DNO, DCOM, DNAME);

乍一看,如果這兩表聯合查詢,應該沒啥問題,通過CNO連結,CNO也在索引中;

實際呢,在TABLE1中,CTYPE=1查出來的CNO,可能不止1個,假設1w個;那麼對於沒個CNO,都會觸發TABLE2進行隨機訪問
我們可以粗略大概計算一下LRT

LRT = 10ms + 1w*0.01ms + 1w * 10ms

對於TABLE1,資料全部在索引中,訪問第一條索引發生了一次隨機訪問,剩餘索引為順序訪問,所以是10ms + 1w*0.01ms
對於TABLE2,其訪問順序取決於TABLE1得到的CNO,CTYPE=1的情況下,CNO順序儲存的概率不大,我們假設他們是分散儲存的,那麼每次FETCH CNO,就會導致一次隨機訪問索引,大概有1W*10ms的時長

最終,查詢速度並不理想,雖然每個表都是最佳索引,問題在哪?在於跨表查詢導致的隨機訪問;
複製程式碼

在上述情況下,如何快速提升速度,如果在設計階段,不妨考慮將兩表合併,或者將CTYPE,也放入到TABLE2中;

往往大家特別排斥冗餘資料,但是從效率的角度出發,冗餘資料真的不好嗎,它的維護成本和效率成本有沒有好好比較一下呢?

當然如果實際執行中資料查詢並不慢,並不需要糾結這些;如果能夠通過寬索引或者半寬索引解決,就最好不要推翻或追加。

3. 設計出色索引的步驟

1.當表結構設計出來時,就該開始索引的設計
2.用BQ或者QUBE進行索引設計檢查,如果還是沒辦法滿足需求,就要考慮合併表,減少跨表
3.根據應用需要嘗試繼續新增必要的索引
4.如果表增刪改的頻率很高(50次/秒),那需要用QUBE評估下最多容許新增多少索引
5.根據具體的資料庫調整策略
6.SQL編寫以後,繼續使用BQ、QUBE、BJQ等方式進行檢查
7.釋出後,使用EXPLAIN進行檢查
8.跟蹤報告
複製程式碼

                                其他相關章節
複製程式碼

資料庫索引相關文章之一:《B樹,一點都不神祕》
資料庫索引相關文章之二:《B樹很簡單,插入so easy》
資料庫索引相關文章之三:《索引》
資料庫索引相關文章之四:《什麼索引算是好的索引》
資料庫索引相關文章之五:《如何發現及替換不合適的索引》
資料庫索引相關文章之六:《索引總結》

相關文章