1樓:
索引可以加快資料檢索操作,但會使資料修改操作變慢。每修改資料記錄,索引就必須重新整理一次。為了在某種程度上彌補這一缺陷,許多sql命令都有一個delay_key_write項。
這個選項的作用是暫時制止mysql在該命令每插入一條新記錄和每修改一條現有之後立刻對索引進行重新整理,對索引的重新整理將等到全部記錄插入/修改完畢之後再進行。在需要把許多新記錄插入某個資料表的場合,delay_key_write選項的作用將非常明顯。
另外,索引還會在硬碟上佔用相當大的空間。因此應該只為最經常查詢和最經常排序的資料列建立索引。如果某個資料列包含許多重複的內容,為它建立索引就沒有太大的實際效果。
擴充套件資料
從理論上講,完全可以為資料表裡的每個欄位分別建一個索引,但mysql把同一個資料表裡的索引總數限制為16個。
與innodb資料表相比,在innodb資料表上,索引對inn資料表的重要性要大得多。在 innodb 資料表上,索引不僅會在搜尋資料記錄時發揮作用,還是資料行級鎖定機制的基礎。
在為mysql分配足夠的記憶體之前,請考慮不同領域對mysql的記憶體需求。要考慮的關鍵領域是:併發連線——對於大量併發連線,排序和臨時表將需要大量記憶體。
在撰寫本文時,對於處理3000+併發連線的資料庫,16gb到32gb的ram是足夠的。
2樓:熱愛資料庫的同學
索引分單列索引和組合索引。
單列索引,即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。
組合索引,即一個索引包含多個列。
建立索引時,你需要確保該索引是應用在 sql 查詢語句的條件(一般作為 where 子句的條件)。
實際上,索引也是一張表,該表儲存了主鍵與索引欄位,並指向實體表的記錄。
上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:
雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行insert、update和delete。因為更新表時,mysql不僅要儲存資料,還要儲存一下索引檔案。
建立索引會佔用磁碟空間的索引檔案。
-from shulanxt
3樓:匿名使用者
索引就像一本書的目錄,例如:你想看一本書的第20章,你會先檢視目錄中第20章所處的頁數,然即時翻到第20章所處的頁數,而不用一頁一頁翻過去,索引相當於目錄功能,助你快速查詢
4樓:匿名使用者
索引會先把索引列按照一定順序排列起來,這樣再找的時候就快的多了。。
5樓:愛可生雲資料庫
在滿足語句需求的情況下,儘量少的訪問資源是資料庫設計的重要原則,這和執行的 sql 有直接的關係,索引問題又是 sql 問題中出現頻率最高的,常見的索引問題包括:無索引(失效)、隱式轉換。1.
sql 執行流程看一個問題,在下面這個表 t 中,如果我要執行 需要執行幾次樹的搜尋操作,會掃描多少行?
這條 sql 語句的執行流程:
1. 在 k 索引樹上找到 k=3,獲得 id=3002. 回表到 id 索引樹查詢 id=300 的記錄,對應 r33.
在 k 索引樹找到下一個值 k=5,id=5004. 再回到 id 索引樹找到對應 id=500 的 r4
5. 在 k 索引樹去下一個值 k=6,不符合條件,迴圈結束
這個過程讀取了 k 索引樹的三條記錄,回表了兩次。因為查詢結果所需要的資料只在主鍵索引上有,所以必須得回表。所以,我們該如何通過優化索引,來避免回表呢?
2. 常見索引優化2.1 覆蓋索引覆蓋索引,換言之就是索引要覆蓋我們的查詢請求,無需回表。
如果執行的語句是 ,這樣的話因為 id 的值在 k 索引樹上,就不需要回表了。
覆蓋索引可以減少樹的搜尋次數,顯著提升查詢效能,是常用的效能優化手段。
但是,維護索引是有代價的,所以在建立冗餘索引來支援覆蓋索引時要權衡利弊。
2.2 最左字首原則
b+ 樹的資料項是複合的資料結構,比如 的時候,b+ 樹是按照從左到右的順序來建立搜尋樹的,當 這樣的資料來檢索的時候,b+ 樹會優先比較 name 來確定下一步的檢索方向,如果 name 相同再依次比較 *** 和 age,最後得到檢索的資料。
可以清楚的看到,a1 使用 tl 索引,a2 進行了全表掃描,雖然 a2 的兩個條件都在 tl 索引中出現,但是沒有使用到 name 列,不符合最左字首原則,無法使用索引。所以在建立聯合索引的時候,如何安排索引內的欄位排序是關鍵。評估標準是索引的複用能力,因為支援最左字首,所以當建立(a,b)這個聯合索引之後,就不需要給 a 單獨建立索引。
原則上,如果通過調整順序,可以少維護一個索引,那麼這個順序往往就是需要優先考慮採用的。上面這個例子中,如果查詢條件裡只有 b,就是沒法利用(a,b)這個聯合索引的,這時候就不得不維護另一個索引,也就是說要同時維護(a,b)、(b)兩個索引。這樣的話,就需要考慮空間佔用了,比如,name 和 age 的聯合索引,name 欄位比 age 欄位佔用空間大,所以建立(name,age)聯合索引和(age)索引佔用空間是要小於(age,name)、(name)索引的。
2.3 索引下推
以人員表的聯合索引(name, age)為例。如果現在有一個需求:檢索出表中“名字第一個字是張,而且年齡是26歲的所有男性”。那麼,sql 語句是這麼寫的
通過最左字首索引規則,會找到 id1,然後需要判斷其他條件是否滿足在 mysql 5.6 之前,只能從 id1 開始一個個回表。到主鍵索引上找出資料行,再對比欄位值。
而 mysql 5.6 引入的索引下推優化(index condition pushdown),可以在索引遍歷過程中,對索引中包含的欄位先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數。這樣,減少了回表次數和之後再次過濾的工作量,明顯提高檢索速度。
2.4 隱式型別轉化
隱式型別轉化主要原因是,表結構中指定的資料型別與傳入的資料型別不同,導致索引無法使用。所以有兩種方案:
修改表結構,修改欄位資料型別。
修改應用,將應用中傳入的字元型別改為與表結構相同型別。
3. 為什麼會選錯索引3.1 優化器選擇索引是優化器的工作,其目的是找到一個最優的執行方案,用最小的代價去執行語句。
在資料庫中,掃描行數是影響執行代價的因素之一。掃描的行數越少,意味著訪問磁碟資料的次數越少,消耗的 cpu 資源越少。當然,掃描行數並不是唯一的判斷標準,優化器還會結合是否使用臨時表、是否排序等因素進行綜合判斷。
3.2 掃描行數
mysql 在真正開始執行語句之前,並不能精確的知道滿足這個條件的記錄有多少條,只能通過索引的區分度來判斷。顯然,一個索引上不同的值越多,索引的區分度就越好,而一個索引上不同值的個數我們稱為“基數”,也就是說,這個基數越大,索引的區分度越好。
mysql 使用取樣統計方法來估算基數:取樣統計的時候,innodb 預設會選擇 n 個資料頁,統計這些頁面上的不同值,得到一個平均值,然後乘以這個索引的頁面數,就得到了這個索引的基數。而資料表是會持續更新的,索引統計資訊也不會固定不變。
所以,當變更的資料行數超過 1/m 的時候,會自動觸發重新做一次索引統計。
在 mysql 中,有兩種儲存索引統計的方式,可以通過設定引數 innodb_stats_persistent 的值來選擇:
on 表示統計資訊會持久化儲存。預設 n = 20,m = 10。
off 表示統計資訊只儲存在記憶體中。預設 n = 8,m = 16。
由於是取樣統計,所以不管 n 是 20 還是 8,這個基數都很容易不準確。所以,冤有頭債有主,mysql 選錯索引,還得歸咎到沒能準確地判斷出掃描行數。
可以用 來重新統計索引資訊,進行修正。
3.3 索引選擇異常和處理1. 採用 force index 強行選擇一個索引。
2. 可以考慮修改語句,引導 mysql 使用我們期望的索引。3.
有些場景下,可以新建一個更合適的索引,來提供給優化器做選擇,或刪掉誤用的索引。