面試中,當面試官問出這個問題時,你以爲這是在考察mysql的什麼內容?我當時腦子過了一下,我知道一條sql在執行的時候,會通過查詢緩存,sql解析器,預處理器,sql優化器,生成執行計劃,調用存儲過程的api,數據,這樣一個大概過程。mysql在選擇索引是在sql優化器這一步,可是具體如何選擇索引的,我並無讀過源碼,因此這個問題就GG了。mysql
回家後,我還在想這題到底考察的什麼,而且查了一些資料,搞清楚了選擇是怎麼一回事。在不考慮臨時表和排序的狀況下,優化器的目的是經過選擇合適索引找到掃描數據行數最少的方案,即選擇「選擇性」較高的索引。選擇性=基數/數據總數。索引基數是數據列所包含的不一樣值的數量。掃描行多少涉及到索引「基數」,可是「基數」經過採樣來統計,自己是估算出來的並且不是實時的,索引數據不夠精準,致使最終選出的方案在優化器看來最優,但實際執行起來並非最優。 mysql 優化器最終選擇哪一個索引,須要具體採樣數據來決定的,咱們並不能看出來或者算出來。面試
可是優化器若是由於不許確的採樣基數,沒法選擇最優索引怎麼辦? 這道題引伸出的考察點如何幹預mysql選擇索引。如何讓 mysql 能選擇咱們爲某個 sql 所設計的最優索引,而不會由於優化器選擇其餘索引致使性能問題。sql
方法一,在sql中經過 force index 指定索引,等於直接告訴優化器不要用你那不靠譜的採樣了,就用這個索引吧。缺點就是耦合性太強,若是你換一個更好的index那你要去改sql了,維護麻煩。 api
方法二,analyze table,主動讓讓索引的基數從新計算一下。缺點,不夠實時,不夠靈活,你不看着點又會跑偏了。緩存
方法三,找出總是被錯誤選擇的索引,若是做用不是很大,簡單粗暴,刪除。整個世界就清爽了。 性能