mysql字段简索引_Mysql索引优化攻略(全)
所謂索引就是為特定的mysql字段進行一些特定的算法排序,比如二叉樹的算法和哈希算法,哈希算法是通過建立特征值,然后根據特征值來快速查找。而用的最多,并且是mysql默認的就是二叉樹算法 BTREE,通過BTREE算法建立索引的字段,比如掃描20行就能得到未使用BTREE前掃描了2^20行的結果。
Explain優化查詢檢測
EXPLAIN可以幫助開發人員分析SQL問題,explain顯示了mysql如何使用索引來處理select語句以及連接表,可以幫助選擇更好的索引和寫出更優化的查詢語句。
使用方法,在select語句前加上Explain就可以了:
mysql在執行一條查詢之前,會對發出的每條SQL進行分析,決定是否使用索引或全表掃描如果發送一條select * from blog where false,Mysql是不會執行查詢操作的,因為經過SQL分析器的分析后MySQL已經清楚不會有任何語句符合操作。
實例
select_typesimple:簡單select(不使用union或子查詢)。
primary:最外面的select。
union:union中的第二個或后面的select語句。
dependent union:union中的第二個或后面的select語句,取決于外面的查詢。
union result:union的結果。
subquery:子查詢中的第一個select。
dependent subquery:子查詢中的第一個select,取決于外面的查詢。
derived:導出表的select(from子句的子查詢)。
其它說明Distinct:一旦MYSQL找到了與行相聯合匹配的行,就不再搜索了。
Not exists: MYSQL優化了LEFT JOIN,一旦它找到了匹配LEFT JOIN標準的行,就不再搜索了。
Range checked for each Record(index map:#):沒有找到理想的索引,因此對于從前面表中來的每一個行組合,MYSQL檢查使用哪個索引,并用它來從表中返回行。這是使用索引的最慢的連接之一。
Using filesort: 看到這個的時候,查詢就需要優化了。MYSQL需要進行額外的步驟來發現如何對返回的行排序。它根據連接類型以及存儲排序鍵值和匹配條件的全部行的行指針來排序全部行。
Using index: 列數據是從僅僅使用了索引中的信息而沒有讀取實際的行動的表返回的,這發生在對表的全部的請求列都是同一個索引的部分的時候。
Using temporary 看到這個的時候,查詢需要優化了。這里,MYSQL需要創建一個臨時表來存儲結果,這通常發生在對不同的列集進行ORDER BY上,而不是GROUP BY上。
Where used 使用了WHERE從句來限制哪些行將與下一張表匹配或者是返回給用戶。如果不想返回表中的全部行,并且連接類型ALL或index,這就會發生,或者是查詢有問題不同連接類型的解釋(按照效率高低的順序排序)。
system 表只有一行:system表。這是const連接類型的特殊情況。
const:表中的一個記錄的最大值能夠匹配這個查詢(索引可以是主鍵或惟一索引)。因為只有一行,這個值實際就是常數,因為MYSQL先讀這個值然后把它當做常數來對待。
eq_ref:在連接中,MYSQL在查詢時,從前面的表中,對每一個記錄的聯合都從表中讀取一個記錄,它在查詢使用了索引為主鍵或惟一鍵的全部時使用。
ref:這個連接類型只有在查詢使用了不是惟一或主鍵的鍵或者是這些類型的部分(比如,利用最左邊前綴)時發生。對于之前的表的每一個行聯合,全部記錄都將從表中讀出。這個類型嚴重依賴于索引匹配的記錄多少,越少越好。
range:這個連接類型使用索引返回一個范圍中的行,比如使用>或
index: 這個連接類型對前面的表中的每一個記錄聯合進行完全掃描(比ALL更好,因為索引一般小于表數據)。
ALL:這個連接類型對于前面的每一個記錄聯合進行完全掃描,這一般比較糟糕,應該盡量避免。
其中type:如果是Only index,這意味著信息只用索引樹中的信息檢索出的,這比掃描整個表要快。
如果是where used,就是使用上了where限制。
如果是impossible where 表示用不著where,一般就是沒查出來啥。
如果此信息顯示Using filesort或者Using temporary的話會很吃力,WHERE和ORDER BY的索引經常無法兼顧,如果按照WHERE來確定索引,那么在ORDER BY時,就必然會引起Using filesort,這就要看是先過濾再排序劃算,還是先排序再過濾劃算。
索引的類型
UNIQUE唯一索引
不可以出現相同的值,可以有NULL值。
INDEX普通索引
允許出現相同的索引內容。
PRIMARY KEY主鍵索引
不允許出現相同的值,且不能為NULL值,一個表只能有一個primary_key索引。
fulltext index 全文索引
上述三種索引都是針對列的值發揮作用,但全文索引,可以針對值中的某個單詞,比如一篇文章中的某個詞。
索引的CURD
索引的創建
ALTER TABLE
適用于表創建完畢之后再添加。
ALTER TABLE 表名 ADD 索引類型 (unique,primary key,fulltext,index)[索引名](字段名)
CREATE INDEX
CREATE INDEX可對表增加普通索引或UNIQUE索引。
另外,還可以在建表時添加:
索引的刪除
索引的查看
索引的更改
刪掉重建一個既可
創建索引的技巧維度高的列創建索引。數據列中不重復值出現的個數,這個數量越高,維度就越高。
如數據表中存在8行數據a,b ,c,d,a,b,c,d這個表的維度為4。
要為維度高的列創建索引,如性別和年齡,那年齡的維度就高于性別。
性別這樣的列不適合創建索引,因為維度過低。
2、對 where,on,group by,order by 中出現的列使用索引。
3、對較小的數據列使用索引,這樣會使索引文件更小,同時內存中也可以裝載更多的索引鍵。
4、為較長的字符串使用前綴索引。
5、不要過多創建索引,除了增加額外的磁盤空間外,對于DML操作的速度影響很大,因為其每增刪改一次就得從新建立索引。
6、使用組合索引,可以減少文件索引大小,在使用時速度要優于多個單列索引。
使用索引的小技巧
1.軸向長度權衡區分度與長度的技巧
截取不同長度,測試區分度
區別度能達到0.1,就可以。
2.左對齊不易區分的細分索引建立方法
這樣的細分,左邊有大量重復字符,某些網址細分匯總的http://倒過來存儲并建立索引
新增偽hash變量把字符串轉化為整型
3.索引覆蓋
概念:如果查詢的列恰好是索引的一部分,那么查詢只需要在索引文件上進行,不需要回行到磁盤,這種查詢,速度極快,江湖人稱-索引覆蓋
4.延遲關聯
在根據條件查詢數據時,如果查詢條件不能用的索引,可以先輸入數據行的id,再根據id去取數據行。
5.索引排序
排序的基線上加入索引,可以提高速度。
6.重復索引和冗余索引
重復索引:在同一列或相同順序的幾個列建立了多個索引,成為重復索引,沒有任何意義,減少了
冗余索引:兩個或多個索引所覆蓋的列有重疊,而對于列m ,n,加索引index m(m),indexmn(m,n),稱為冗余索引。
7.索引碎片與維護
在數據表長期的更改過程中,索引文件和數據文件都會產生空洞,形成碎片。修復表的過程十分耗費資源,可以用比較長的周期修復表。
8. innodb引擎的索引注意事項
Innodb表要嘗試自己指定主鍵,如果有幾個列都是唯一的,要選擇最常作為訪問條件的列作為主鍵,另外,Innodb表的普通索引都會保存主鍵的鍵值,因此主鍵要進行選擇快照的數據類型,可以有效的減少索引的磁盤占用,提高索引的緩存效果。
組合索引與前綴索引
注意,這兩種稱呼是對建立索引技巧的一種稱呼,并非索引的類型。
組合索引
MySQL單列索引和組合索引究竟有何區別呢?
為了形象地對比兩者,先建一個表:
假設表內已有1000條數據,在這 10000 條記錄里面 7 上 8 下地分布了 5 條 vc_Name=”erquan” 的記錄,只不過 city,age,school 的組合各不相同。來看這條 T-SQL:
首先考慮建MySQL單列索引:
在 vc_Name 列上建立了索引。執行 T-SQL 時,MYSQL 很快將目標鎖定在了 vc_Name=erquan 的 5 條記錄上,取出來放到一中間結果集。在這個結果集里,先排除掉 vc_City 不等于”鄭州”的記錄,再排除 i_Age 不等于 25 的記錄,最后篩選出唯一的符合條件的記錄。雖然在 vc_Name 上建立了索引,查詢時MYSQL不用掃描整張表,效率有所提高,但離我們的要求還有一定的距離。同樣的,在 vc_City 和 i_Age 分別建立的MySQL單列索引的效率相似。
為了進一步榨取 MySQL 的效率,就要考慮建立組合索引。就是將 vc_Name,vc_City,i_Age 建到一個索引里:
建表時,vc_Name 長度為 50,這里為什么用 10 呢?這就是下文要說到的前綴索引,因為一般情況下名字的長度不會超過 10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高 INSERT 的更新速度。
執行 T-SQL 時,MySQL 無須掃描任何記錄就到找到唯一的記錄!
如果分別在 vc_Name,vc_City,i_Age 上建立單列索引,讓該表有 3 個單列索引,查詢時和上述的組合索引效率一樣嗎?答案是大不一樣,遠遠低于我們的組合索引。雖然此時有了三個索引,但 MySQL 只能用到其中的那個它認為似乎是最有效率的單列索引,另外兩個是用不到的,也就是說還是一個全表掃描的過程。
建立這樣的組合索引,其實是相當于分別建立了:vc_Name,vc_City,i_Age
vc_Name,vc_City
vc_Name
這樣的三個組合索引!為什么沒有 vc_City,i_Age 等這樣的組合索引呢?這是因為 mysql 組合索引 “最左前綴” 的結果。簡單的理解就是只從最左面的開始組合。并不是只要包含這三列的查詢都會用到該組合索引,下面的幾個 T-SQL 會用到:SELECT * FROM myIndex WHREE vc_Name=”erquan” AND vc_City=”鄭州” SELECT * FROM myIndex WHREE vc_Name=”erquan”
而下面幾個則不會用到:SELECT * FROM myIndex WHREE i_Age=20 AND vc_City=”鄭州” SELECT * FROM myIndex WHREE vc_City=”鄭州”
也就是,name_city_age(vc_Name(10),vc_City,i_Age) 從左到右進行索引,如果沒有左前索引Mysql不執行索引查詢。
前綴索引
如果索引列長度過長,這種列索引時將會產生很大的索引文件,不便于操作,可以使用前綴索引方式進行索引前綴索引應該控制在一個合適的點,控制在0.31黃金值即可(大于這個值就可以創建)。
SELECT COUNT(DISTINCT(LEFT(title,10)))/COUNT(*) FROM Arctic; — 這個值大于0.31就可以創建前綴索引,Distinct去重復 ALTER TABLE?user?ADD INDEX?uname(title(10)); — 增加前綴索引SQL,將人名的索引建立在10,這樣可以減少索引文件大小,加快索引查詢速度。
什么樣的sql不走索引
要盡量避免這些不走索引的sql
多表關聯時的索引效率SELECT?sname?FROM?stu?WHERE LEFT(date,4) <1990; — 不會使用索引,因為使用了函數運算,原理與上面相同
SELECT * FROM?houdunwang?WHERE?uname?LIKE’后盾%’ — 走索引
SELECT * FROM?houdunwang?WHERE?uname?LIKE “%后盾%” — 不走索引
從上圖可以看出,所有表的type為all,表示全表索引。也就是6 6 6,共遍歷查詢了216次。
除第一張表示全表索引(必須的,要以此關聯其他表),其余的為range(索引區間獲得),也就是6+1+1+1,共遍歷查詢9次即可。
所以我們建議在多表join的時候盡量少join幾張表,因為一不小心就是一個笛卡爾乘積的恐怖掃描,另外,我們還建議盡量使用left join,以少關聯多。因為使用join 的話,第一張表是必須的全掃描的,以少關聯多就可以減少這個掃描次數。
索引的弊端
不要盲目的創建索引,只為查詢操作頻繁的列創建索引,創建索引會使查詢操作變得更加快速,但是會降低增加、刪除、更新操作的速度,因為執行這些操作的同時會對索引文件進行重新排序或更新。
但是,在互聯網應用中,查詢的語句遠遠大于DML的語句,甚至可以占到80%~90%,所以也不要太在意,只是在大數據導入時,可以先刪除索引,再批量插入數據,最后再添加索引。
更多學習內容可以訪問https://zhuanlan.zhihu.com/p/165932664
以上內容希望幫助到大家,很多PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那里入手去提升,對此我整理了一些資料,包括但不限于:分布式架構、高可擴展、高性能、高并發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階干貨需要的可以免費分享給大家,需要的可以加入我的PHP技術交流群953224940還有更多學習資料等你來領取噢進階PHP月薪30k>>>架構師成長路線【視頻、面試文檔免費獲取】(https://shimo.im/docs/Jky8td8RTvHTG6k9)
總結
以上是生活随笔為你收集整理的mysql字段简索引_Mysql索引优化攻略(全)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python三级联动菜单_详解eleme
- 下一篇: oracle改字体大小_oracle数据