MySQL理解索引、添加索引的原則

轉自:MySQL理解索引、添加索引的原則

索引用於快速找出在某個列中有一特定值的行。不使用索引,MySQL必須從第1條記錄開始然後讀完整個表直到找出相關的行,還需要考慮每次讀入數據頁的IO開銷。而如果採取索引,則可以根據索引指向的頁以及記錄在頁中的位置,迅速地讀取目標頁進而獲取目標記錄。

大多數情況下都(默認)採用B樹來構建索引。只是空間列類型的索引使用R-樹,並且MEMORY表還支持hash索引。B樹是平衡多叉樹,每個節點存放多少個值取決於值所佔的空間,這與每一張數據頁存放多少條記錄與記錄信息量有關同理。節點中的值是以非降序進行排列的,節點中的值總是小於等於指向它的結點中的值。

MySQL使用B樹構造索引的情況下,是由葉子指向具體的頁和記錄的。並且一個葉子有一個指針指向下一個葉子。

 

使用索引需要注意:

⑴只對WHERE和ORDER BY需要查詢的字段設置索引,避免無意義的硬盤開銷;

⑵組合索引支持前綴索引;

⑶更新表的時候,如增刪記錄,MySQL會自動更新索引,保持樹的平衡;因此更多的索引意味着更多的維護成本

 索引的字段類型問題

  • text類型,也可建索引(需指定長度)
  • myisam存儲引擎索引鍵長度綜合不能超過1000字節
  • 用來篩選的值儘量保持和索引列同樣的數據類型

索引分四類:

index ----普通的索引,數據可以重複

fulltext----全文索引,用來對大表的文本域(char,varchar,text)進行索引。語法和普通索引一樣。 

unique ----唯一索引,唯一索引,要求所有記錄都唯一

primary key ----主鍵索引,也就是在唯一索引的基礎上相應的列必須爲主鍵

like 不能用索引?

  • 儘量減少like,但不是絕對不可用,”xxxx%” 是可以用到索引的,

想象一下,你在看一本成語詞典,目錄是按成語拼音順序建立,查詢需求是,你想找以 “一”字開頭的成語(”一%“),和你想找包含一字的成語(“%一%”)

  • 除了like,以下操作符也可用到索引:

<,<=,=,>,>=,BETWEEN,IN

<>,not in ,!=則不行

 

原則

   1,單表數據太少,索引反而會影響速度;更新非常頻繁的數據不適宜建索引

   2,where後的條件,order by ,group by 等這樣過濾時,後面的字段最好加上索引。根據實際情況,選擇PRIMARY KEY、UNIQUE、INDEX等索引,但是不是越多越好,要適度

    3,聯合查詢,子查詢等多表操作時關連字段要加索引

ps:數據量特別大的時候,最好不要用聯合查詢,即使你做了索引

多列查詢該如何建索引?

一次查詢只能用到一個索引,所以 首先槍斃 a,b各建索引方案

a還是b? 誰的區分度更高(同值的最少),建誰!

當然,聯合索引也是個不錯的方案,ab,還是ba,則同上,區分度高者,在前

聯合索引的問題?

where a = “xxx” 可以使用 AB 聯合索引
where b = “xxx” 則不可 (再想象一下,這是書的目錄?)

所以,大多數情況下,有AB索引了,就可以不用在去建一個A索引了

詳解:

聯合索引又叫複合索引。對於複合索引:Mysql從左到右的使用索引中的字段,一個查詢可以只使用索引中的一部份,但只能是最左側部分。例如索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3種組合進行查找,但不支持 b,c進行查找 .當最左側字段是常量引用時,索引就十分有效。


兩個或更多個列上的索引被稱作複合索引。
利用索引中的附加列,您可以縮小搜索的範圍,但使用一個具有兩列的索引 不同於使用兩個單獨的索引。複合索引的結構與電話簿類似,人名由姓和名構成,電話簿首先按姓氏對進行排序,然後按名字對有相同姓氏的人進行排序。如果您知 道姓,電話簿將非常有用;如果您知道姓和名,電話簿則更爲有用,但如果您只知道名不姓,電話簿將沒有用處。
所以說創建複合索引時,應該仔細考慮列的順序。對索引中的所有列執行搜索或僅對前幾列執行搜索時,複合索引非常有用;僅對後面的任意列執行搜索時,複合索引則沒有用處。
如:建立 姓名、年齡、性別的複合索引。

create table test(
a int,
b int,
c int,
KEY a(a,b,c)
);

優: select * from test where a=10 and b>50
差: select * from test where a50

優: select * from test order by a
差: select * from test order by b
差: select * from test order by c

優: select * from test where a=10 order by a
優: select * from test where a=10 order by b
差: select * from test where a=10 order by c

優: select * from test where a>10 order by a
差: select * from test where a>10 order by b
差: select * from test where a>10 order by c

優: select * from test where a=10 and b=10 order by a
優: select * from test where a=10 and b=10 order by b
優: select * from test where a=10 and b=10 order by c

優: select * from test where a=10 and b=10 order by a
優: select * from test where a=10 and b>10 order by b
差: select * from test where a=10 and b>10 order by c



索引原則

1.索引越少越好
原因:主要在修改數據時,第個索引都要進行更新,降低寫速度。
2.最窄的字段放在鍵的左邊
3.避免file sort排序,臨時表和表掃描.

哪些常見情況不能用索引?

  • like “%xxx”
  • not in , !=
  • 對列進行函數運算的情況(如 where md5(password) = “xxxx”)
  • WHERE index=1 OR A=10
  • 存了數值的字符串類型字段(如手機號),查詢時記得不要丟掉值的引號,否則無法用到該字段相關索引,反之則沒關係

也即

select * from test where mobile = 13711112222;

可是無法用到mobile字段的索引的哦(如果mobile是char 或 varchar類型的話)

btw,千萬不要嘗試用int來存手機號(爲什麼?自己想!要不自己試試)

 

覆蓋索引(Covering Indexes)擁有更高效率

索引包含了所需的全部值的話,就只select 他們,換言之,只select 需要用到的字段,如無必要,可儘量避免select *

NULL 的問題

NULL會導致索引形同虛設,所以在設計表結構時應避免NULL 的存在(用其他方式表達你想表達的NULL,比如 -1?)

如何查看索引信息,如何分析是否正確用到索引?

show index from tablename;
explain select ……;

關於explain,改天可以找個時間專門寫一篇入門帖,在此之前,可以嘗試 google

瞭解自己的系統,不要過早優化!

過早優化,一直是個非常討厭而又時刻存在的問題,大多數時候就是因爲不瞭解自己的系統,不知道自己系統真正的承載能力

比如:幾千條數據的新聞表,每天幾百幾千次的正文搜索,大多數時候我們可以放心的去like,而不要又去建一套全文搜索什麼的,畢竟cpu還是比人腦厲害太多

最後:永遠別忘記的關鍵詞 sql注入

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章