如何發現及替換不合適的索引

2021-09-24 08:17:29 字數 3041 閱讀 7922

複製**

觸發我們考慮考慮索引是否合適的契機有兩種

一種是:生產環境**現查詢慢,我們急於解決現實遇到的問題;

一種是:在設計實現階段,我們希望提前發現設計不合理的索引,以免後續發布以後才出現效能問題;

複製**

對於情況,我們可以通過提問來反思如何改進索引。

1. 是否所有where子句中的所有列都在索引中了?

如果沒有,則新增到索引中,將索引變成半寬索引

2. 是否將所有涉及的列都加入到索引中了?

如果變成半寬索引後,還是沒有解決到效能問題,那麼下乙個選擇就是將查詢中所有涉及的列都加入到索引中,形成寬索引;這樣,優化器的訪問只需訪問索引,避免了表訪問。

3. 你需要最佳索引

如果上述兩種方式,仍未解決效能問題,則要參考《什麼是最好的索引》一文,好好考慮一下索引的設計了

例如:select a from *** where b = 1 and c = 2;而索引是(a, b, c) 按照《索引》中的優化器邏輯,其索引片是空,即其查詢將進行全索引掃瞄;如果索引超過10w條記錄,那麼查詢將會很慢

但是按照上述的檢查方式,第一條和第二條其都是滿足的,但是該索引在一定的數量級下依然會導致查詢效率慢,那麼就要做第三步,對索引進行重新考慮了。

在正式執行的系統中,建議擴充索引列,而不是新增新的索引或者更換索引列的順序,和將帶來額外的負擔。

對於情況,我們可以通過系統的評估來檢視索引是否合適。

1. 統計本地相應時間

直接先上結論:

本地響應時間(lrt) = 隨機訪問的數量(tr) * 10ms + 順序訪問數量(ts) * 0.01ms + 有效fetch數量(f) * 0.1ms

什麼是隨機訪問:就是一次磁碟io的時間,約為10ms

什麼是順序訪問:一頁包含n行,每行的時間約為0.01ms;

再詳細一點:

dbms讀取乙個索引或乙個錶行的成本,即為一次訪問;

dbms掃瞄索引或表的乙個片段,其中第一行的讀取即為一次隨機訪問;

對於後續行的讀取,每行都是一次順序訪問;

打個比方:

對於去超市買10個罐頭:

隨機訪問就好比在超市找到罐頭的貨架的時間,就是10ms

順序訪問就好比已經找到罐頭的貨架了,只要乙個個把罐頭拿下來,每個罐頭的時間就是0.01ms

好了,知道了隨機訪問和順序訪問,接下來我們知道如何確定隨機訪問和順序訪問的次數

索引訪問次數

可以將索引當成一張表,其行數與其包含的表的行數相同,且按照索引鍵值排列

表訪問次數

我們假設一次全表掃瞄將需要一次隨機訪問和n-1次順序訪問

2.舉例

主鍵索引:select cname, cno, cdesc from table1 where cno = 221

其中cno為主鍵;

索引儲存如下:

111,

112,

113

...

221,

222

那麼優化器是如何檢索的?

i. 根據cno=221,進行一次隨機訪問,取到221這條索引

ii. 根據221這條索引指向的磁碟位置,通過一次隨機訪問,找到資料塊,得到cname,cdesc

那麼lrt是多少?

很好計算: 兩次隨機訪問 + 1次fetch = 2 * 10ms + 0.1ms 約等於 20ms

select cno, cname, cdesc from table1 where ctype = 1 and cname = 'zhang' order by cdesc

假設索引是(ctype, cname, cdesc) 假設ctype =1 和cname='zhang'能從10w的索引中過濾出1000條

1000條索引如下:

1,'zhang', 1

1,'zhang', 2

....

1,'zhang', 1000

那麼lrt是多少?

首先,一次隨機訪問索引的時間,定位到索引1000條的第一行

其次, 1000次順序訪問索引的時間

然後,因cno不在索引中,所以還需要通過索引進行磁碟查詢;

因為是聚簇索引,所以表的順序和索引的順序是一致的,訪問表的時間和索引是一樣的,即一次隨機訪問表的時間,和1000次順序訪問的時間(999不好計算,我們都約等於1000)

lrt= 1次索引隨機訪問 + 1000次索引順序訪問 + 1次表隨機訪問 + 1000次表順序訪問 + 1000次fetch

= 10ms + 1000 * 0.01ms + 10ms + 1000 * 0.01ms + 1000 * 0.1ms

= 140ms

同2.2 ,如果同樣是該查詢語句,但是索引變成非聚簇索引會怎麼樣?

很顯然,表的儲存會發生變化,不再是跟索引的順序一致,並且不是連續儲存了;

所以,lrt = 1次索引隨機訪問 + 1000次索引順序訪問 + 1000次表隨機訪問 + 1000次fetch

= 10ms + 1000 * 0.01ms + 1000 * 10ms + 1000 * 0.1ms

= 10s(約等於)

你看,同樣的1000條索引,查詢速度和2.2相差這麼多!

這個索引該如何優化呢,很顯然,如果它不是聚簇索引,就要將cno納入到索引中來,避免表的隨機訪問;將所有的訪問都回到索引內部

很顯然,這就是《什麼索引是好的索引》中介紹的所謂的好的索引,知識都是相輔相成的。

使用了該更改後的索引,其lrt會變成多少?

lrt = 10ms + 1000 * 0.01ms + 1000 * 0.1ms = 120ms

速度提公升了100倍!

其他相關章節

複製**

程式設計師面試寶典 檢測並修改不合適的繼承

面試例題1 如果鳥是可以飛的,那麼鴕鳥是鳥麼?鴕鳥如何繼承鳥類?美國某著名分析軟體公司2005年面試題 解析 如果所有鳥都能飛,那鴕鳥就不是鳥!回答這種問題時,不要相信自己的直覺!將直覺和合適的繼承聯絡起來還需要一段時間。根據題幹可以得知 鳥是可以飛的。也就是說,當鳥飛行時,它的高度是大於0的。鴕鳥...

rust怎麼不要的牆拆掉 馬桶坑距不合適,怎麼辦?

現在很多家庭都裝馬桶,所以大家應該也都知道坑距是怎麼回事,不過為了照顧裝修小白,我在這裡還是科普一下。坑距,指的是馬桶的下水管中心到牆體之間的距離。在購買馬桶之前,如果衛生間準備貼瓷磚,那就最好是在貼完以後再去測量坑距 如果衛生間已經裝了吊頂,那就需要將扣板給拆掉一部分,再進行測量 如果還是毛坯房的...

0929mysql字首索引如何找到合適的位數

字首索引,是指對於varchar text blob型別的字段建立索引時一般都會選擇前n個字元作為索引。索引很長的字元列,會讓索引變得大且慢。索引開始的部分字元,這樣可以大大節約索引空間,從而提高索引效率,但這樣也會降低索引的選擇性。索引的選擇性是指不重複的索引值 也稱為基數,cardinality...