(一)MySQL优化之索引优化
一、索引的概念
我們知道,在查詢過程中,如果被查詢的表沒有索引,數據庫會進行全表掃描,而如果添加了相應的索引,數據庫會根據索引直接查找符合條件的數據。因此,索引的存在會大大提高查詢效率。而索引其實就是一個特殊文件(InnoDB中索引是表空間的一部分),它包含碰上對表中所有記錄的引用指針。
二、索引的分類
索引可以分為兩種:聚簇索引和非聚簇索引。
(一)聚簇索引
聚簇索引是按照每張表的主鍵構造一顆B+樹,同時葉子節點中存放的就是整張表的行記錄數據,也將聚集索引的葉子節點稱為數據頁。這個特性決定了索引組織表中數據也是索引的一部分,每張表只能擁有一個聚簇索引。
(二)非聚簇索引
非聚簇索引使用B+Tree作為索引結構,葉節點的data域存放的是數據記錄的地址。查詢先通過索引查找到符合條件的地址,然后通過地址查再找數據。
(三)兩種索引的區別
1.聚簇索引是和數據在一起的,通過索引即可一次性查詢出數據。
2.非聚簇索引索引文件和數據是獨立的,查詢會先查找到符合條件的索引,通過地址進行二次查找表中的數據。
3.聚簇索引的效率比非聚簇索引的高。
4.由于節子節點(數據頁)只能按照一顆B+樹排序,故一張表只能有一個聚簇索引。輔助索引的存在不影響聚簇索引中數據的組織,所以一張表可以有多個輔助索引。
(四) 應用
1.InnoDB存儲引擎
1.1 主鍵索引
InnoDB存儲引擎主鍵索引使用的是聚簇索引,如果沒有定義主鍵,innodb會選擇非空的唯一索引代替。如果沒有這樣的索引,innodb會隱式的定義一個主鍵來作為聚簇索引。
優點:
1.數據訪問更快,因為聚簇索引將索引和數據保存在同一個B+樹中,因此從聚簇索引中獲取數據比非聚簇索引更快
2.聚簇索引對于主鍵的排序查找和范圍查找速度非常快
缺點:
1.插入速度嚴重依賴于插入順序,按照主鍵的順序插入是最快的方式,否則將會出現頁分裂,嚴重影響性能。因此,對于InnoDB表,我們一般都會定義一個自增的ID列為主鍵
2.更新主鍵的代價很高,因為將會導致被更新的行移動。因此,對于InnoDB表,我們一般定義主鍵為不可更新。
1.2 輔助索引(又叫非聚簇索引)
InnoDB的所有輔助索引都引用主鍵作為data域。
InnoDB 表是基于聚簇索引建立的。因此InnoDB 的索引能提供一種非常快速的主鍵查找性能。不過,它的輔助索引(Secondary Index, 也就是非主鍵索引)也會包含主鍵列,所以,如果主鍵定義的比較大,輔助索引也將很大。如果想在表上定義 、很多索引,則爭取盡量把主鍵定義得小一些。InnoDB 不會壓縮索引。
文字符的ASCII碼作為比較準則。聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。
不同存儲引擎的索引實現方式對于正確使用和優化索引都非常有幫助,例如知道了InnoDB的索引實現后,就很容易明白:
1、為什么不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,
2、用非單調的字段作為主鍵在InnoDB中不是個好主意,因為InnoDB數據文件本身是一顆B+Tree,非單調的主鍵會造成在插入新記錄時數據文件為了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段作為主鍵則是一個很好的選擇。
2.MyISAM存儲引擎
MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。
在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重復。
由此可知,MyISAM存儲引擎的索引都是非聚簇索引。但是由于其主鍵索引和輔助索引存儲的都是鍵的地址,兩者是獨立的索引樹,因此與InnoDB不同的是,輔助索引不用依賴和訪問主索引的索引樹。
參考博客:https://www.cnblogs.com/jiawen010/p/11805241.html
三、索引的優缺點
(一)優點
1.唯一索引可以保證數據唯一性。
2.添加索引可以大大提高查詢效率。
3.加速表與表之間的連接。
4.通過使用索引,可以在查詢過程中,使用優化隱藏器提高系統性能。
(二)缺點
1.創建和維護索引要消耗時間,而且這種時間會隨著數據量的增加而增加。
2.索引會占用物理空間,聚簇索引占用的空間會更大。在InnoDB中,由于輔助索引B+樹的葉子上會存儲主鍵數據,因此主鍵長度也要盡量定義小一些。
3.由于增、刪、改操作的時候,索引也要動態維護,這樣也就降低了數據維護的速度。
四、創建索引的注意事項
一般來說,以下字段適合創建索引:
1.經常查詢的字段:可以提高查詢速度。
2.主鍵字段:強調主鍵的唯一性,有助于組織表數據的排列結構。
3.經常使用的連接鍵:加快連接速度。
4.經常需要進行范圍查詢的列:因為索引是有序的,其指定的范圍也是連續的。
5.經常使用的排序字段:因為索引是有序的,可以利用索引的排序加快查詢速度。
6.常用的where語句過濾條件。
一般來說,以下字段不太適合創建索引:
1.查詢中很少使用的列:額外的索引會增大磁盤的需求,也會額外增加維護成本。
2.有大量重復數據的字段:對查詢并沒有明顯的效果。
3.對于text,image,bit數據類型字段:這些列的數據量太大,可是我們查詢中一般只截取使用其中的一小段數據。
4.對于修改遠遠大于檢索需求的列,不應該建立索引。即使創建索引會增加查詢效率,但是大大降低修改的性能,增加維護成本。
五、Mysql索引的類型和創建
這里不在過多贅述,請自行百度。
要說明的兩點是
1.組合索引根據最左前綴的規則,查詢會從最左邊的索引字段開始組合。如果查詢中沒有使用索引中最左側的字段,將不會使用該組合索引。
六、Mysql索引優化
優化不是一成不變的,版本不同,優化也有可能會不一樣。以下僅供參考:
1.范圍字段多使用聚簇索引:
因為聚簇索引只需要查找到所需數據的開頭和結尾即可,而非聚簇索引要查到每一項數據對應的頁碼,再根據頁碼查找具體數據。2.少數不同值的列推薦使用聚類索引;
3.頻繁修改更新的列推薦使用非聚集索引;
4.where條件中,字段類型不匹配也不會使用索引;
比如SKU為8位數字組成的字符串,如果用 SKU='12345678’會使用索引,但是使用 SKU = 12345678 則不會使用索引。
5.LIKE模糊查詢
索引根據最左前綴原則,右側模糊查詢可以使用索引,左模糊不行。例如:假設字段CLOUMN_1有索引,那么 CLOUMN_1 LIKE 'ABCD%' 可以使用索引; CLOUMN_1 LIKE '%ABCD' 以及 CLOUMN_1 LIKE '%ABCD%' 不能使用索引。6.使用短索引
如果列的值都比較長,如果前10或20個字符多數值是唯一的,就不需要對整個列的數據進行索引。短索引不僅可以提高查詢速度,還可以節省磁盤和IO操作。7.索引列排序
Mysql查詢時只會使用一個索引,如果where條件中已經使用了索引,那么order by中的列是不會使用索引的。 因此如果默認排序可以符合要求的情況下,不要使用排序操作; 盡量不要包含多個列的排序,如果需要最好給這些列創建合適的復合索引。8.where語句中,不要在索引列上使用函數或進行運算
如果對索引列進行運算或使用函數,會導致索引失效。
9.where條件中使用<> 或 != 也會做全表掃描,IS NULL/ IS NOT NULL 有時也會使索引失效
索引失效一般是由于mysql優化器會對查詢的數據做一個數量的預估,如果我們用 is null,有空字段的索引一般是非聚簇索引。這種索引我們進行一次查詢后,得到的是聚簇索引的主鍵,然后我們再進行回表,才能得到數據,這樣優化器會根據空值的多少,自動選擇開銷比較小的方案進行優化。比如我們空值比較少,這時非聚簇索引查找的數據比較精準,開銷也比較少,mysql就會使用索引進行查詢。反之,如果空值比較多,這樣我們如果使用聚簇索引先查詢滿足條件的主鍵,然后再通過大量的回表操作,才能得到我們想要的查詢結果,頻繁的IO就會造成性能開銷較大,mysql就會選擇不走索引的查詢方式。也就是說能不能用到索引,mysql是根據具體情況來決定的。
10.盡量避免使用OR來連接條件,這樣也會導致索引失效。
如果查詢語句的條件中,我們必須使用OR,我們可以采用union all來代替,比如:
select cname from t where id = 10 or id = 20; -- 我們可以改寫為 select cname from t where id = 10 union all select cname from t where id = 20;11. in 和 not in 也要慎用;
12.如果過濾的數值是連續的,能用between就不要用in;
13.如果條件中使用了變量,mysql也會放棄索引,進行全表掃描;
因為sql只有在運行時,才會解析變量值,而優化器是在執行器之前運行的。這樣優化器就無法獲得變量的值,因而無法做為索引過濾輸入項。不過,我們可以強制查詢使用索引,比如:
select cname from t where id = $sid; -- 可以使用下面的sql進行優化: select cname from t with(index(索引名)) where id = $sid;14.在使用復合索引時,必須使用到該索引的第一個字段做為條件才能保證查詢過程使用該復合索引。盡量保持條件字段順序與索引字段順序一致。
15.在優化過程中,很多時候會用exists 代替in。
16.字段有大量重復數據的時候不建議建立索引,即使建立索引,mysql一般也不會使用索引,即使使用對性能也影響不大。如果數據量比較大,也會增加維護成本。
17.索引并不是越多越好,索引能提高查詢效率,但也同時降低了增、刪、改的效率,因為insert、select有時可能會重建索引。一個表的索引數一般不超過6個。
總結
以上是生活随笔為你收集整理的(一)MySQL优化之索引优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VC动态数组实现
- 下一篇: 09 - java 包命名规范