1. ? ? 索引及查詢優(yōu)化
索引的類型
??普通索引:這是最基本的索引類型,沒唯一性之類的限制。
??唯一性索引:和普通索引基本相同,但所有的索引列值保持唯一性。
??主鍵:主鍵是一種唯一索引,但必須指定為”PRIMARY KEY”。
??全文索引:MYSQL從3.23.23開始支持全文索引和全文檢索。在MYSQL中,全文索引的索引類型為FULLTEXT。全文索引可以在VARCHAR或者TEXT類型的列上創(chuàng)建。
大多數(shù)MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)使用B樹中存儲。空間列類型的索引使用R-樹,MEMORY表支持hash索引。
單列索引和多列索引(復(fù)合索引)
索引可以是單列索引,也可以是多列索引。對相關(guān)的列使用索引是提高SELECT操作性能的最佳途徑之一。
多列索引:
MySQL可以為多個列創(chuàng)建索引。一個索引可以包括15個列。對于某些列類型,可以索引列的左前綴,列的順序非常重要。
多列索引可以視為包含通過連接索引列的值而創(chuàng)建的值的排序的數(shù)組。一般來說,即使是限制最嚴(yán)格的單列索引,它的限制能力也遠(yuǎn)遠(yuǎn)低于多列索引。
最左前綴
多列索引有一個特點(diǎn),即最左前綴(Leftmost Prefixing)。假如有一個多列索引為key(firstname lastname age),當(dāng)搜索條件是以下各種列的組合和順序時,MySQL將使用該多列索引:
firstname,lastname,age
firstname,lastname
firstname
也就是說,相當(dāng)于還建立了key(firstname lastname)和key(firstname)。
索引主要用于下面的操作:
??快速找出匹配一個WHERE子句的行。
??刪除行。當(dāng)執(zhí)行聯(lián)接時,從其它表檢索行。
??對具體有索引的列key_col找出MAX()或MIN()值。由預(yù)處理器進(jìn)行優(yōu)化,檢查是否對索引中在key_col之前發(fā)生所有關(guān)鍵字元素使用了WHERE?key_part_#?=?constant。在這種情況下,MySQL為每個MIN()或MAX()表達(dá)式執(zhí)行一次關(guān)鍵字查找,并用常數(shù)替換它。如果所有表達(dá)式替換為常量,查詢立即返回。例如:
SELECT MIN(key2), MAX (key2)??FROM?tb?WHERE?key1=10;
??如果對一個可用關(guān)鍵字的最左面的前綴進(jìn)行了排序或分組(例如,ORDER BY key_part_1,key_part_2),排序或分組一個表。如果所有關(guān)鍵字元素后面有DESC,關(guān)鍵字以倒序被讀取。
??在一些情況中,可以對一個查詢進(jìn)行優(yōu)化以便不用查詢數(shù)據(jù)行即可以檢索值。如果查詢只使用來自某個表的數(shù)字型并且構(gòu)成某些關(guān)鍵字的最左面前綴的列,為了更快,可以從索引樹檢索出值。
SELECT?key_part3?FROM?tb?WHERE?key_part1=1
有時MySQL不使用索引,即使有可用的索引。一種情形是當(dāng)優(yōu)化器估計(jì)到使用索引將需要MySQL訪問表中的大部分行時。(在這種情況下,表掃描可能會更快些)。然而,如果此類查詢使用LIMIT只搜索部分行,MySQL則使用索引,因?yàn)樗梢愿斓卣业綆仔胁⒃诮Y(jié)果中返回。
合理的建立索引的建議:
(1)? 越小的數(shù)據(jù)類型通常更好:越小的數(shù)據(jù)類型通常在磁盤、內(nèi)存和CPU緩存中都需要更少的空間,處理起來更快。
(2)? 簡單的數(shù)據(jù)類型更好:整型數(shù)據(jù)比起字符,處理開銷更小,因?yàn)樽址谋容^更復(fù)雜。在MySQL中,應(yīng)該用內(nèi)置的日期和時間數(shù)據(jù)類型,而不是用字符串來存儲時間;以及用整型數(shù)據(jù)類型存儲IP地址。
(3)? 盡量避免NULL:應(yīng)該指定列為NOT NULL,除非你想存儲NULL。在MySQL中,含有空值的列很難進(jìn)行查詢優(yōu)化,因?yàn)樗鼈兪沟盟饕⑺饕慕y(tǒng)計(jì)信息以及比較運(yùn)算更加復(fù)雜。你應(yīng)該用0、一個特殊的值或者一個空串代替空值
這部分是關(guān)于索引和寫SQL語句時應(yīng)當(dāng)注意的一些瑣碎建議和注意點(diǎn)。
1.當(dāng)結(jié)果集只有一行數(shù)據(jù)時使用LIMIT 1
2.避免SELECT *,始終指定你需要的列
從表中讀取越多的數(shù)據(jù),查詢會變得更慢。他增加了磁盤需要操作的時間,還是在數(shù)據(jù)庫服務(wù)器與WEB服務(wù)器是獨(dú)立分開的情況下。你將會經(jīng)歷非常漫長的網(wǎng)絡(luò)延遲,僅僅是因?yàn)閿?shù)據(jù)不必要的在服務(wù)器之間傳輸。
3.使用連接(JOIN)來代替子查詢(Sub-Queries)
連接(JOIN).. 之所以更有效率一些,是因?yàn)镸ySQL不需要在內(nèi)存中創(chuàng)建臨時表來完成這個邏輯上的需要兩個步驟的查詢工作。
4.使用ENUM、CHAR而不是VARCHAR,使用合理的字段屬性長度
5.盡可能的使用NOT NULL
6.固定長度的表會更快
7.拆分大的DELETE或INSERT語句
8.查詢的列越小越快
Where條件
在查詢中,WHERE條件也是一個比較重要的因素,盡量少并且是合理的where條件是很重要的,盡量在多個條件的時候,把會提取盡量少數(shù)據(jù)量的條件放在前面,減少后一個where條件的查詢時間。
有些where條件會導(dǎo)致索引無效:
??where子句的查詢條件里有!=,MySQL將無法使用索引。
??where子句使用了Mysql函數(shù)的時候,索引將無效,比如:select * from tb where left(name, 4) = ‘xxx’
??使用LIKE進(jìn)行搜索匹配的時候,這樣索引是有效的:select * from tbl1 where name like ‘xxx%’,而like ‘%xxx%’ 時索引無效