使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構, 與必須搜索表中的全部行相比,索引會幫助您更快地得到該信息。
索引提供指向存儲在表的指定列中的數據值的指針,而後根據您指定的排序順序對這些指針排序。數據庫使用索引的方式與您使用書籍中的索引的方式很類似:它搜索索引以找到特定值,而後順指針找到包含該值的行。mysql
做爲通用規則,只有當常常查詢索引列中的數據時,才須要在表上建立索引。索引佔用磁盤空間,而且下降添加、刪除和更新行的速度。sql
若是常常同時搜索兩列或多列或按兩列或多列排序時,索引也頗有幫助。例如,若是常常在同一查詢中爲姓和名兩列設置判據,那麼在這兩列上建立多列索引將頗有意義。數據庫
索引類型
根據數據庫的功能,能夠在數據庫設計器中建立三種索引:惟一索引、主鍵索引和彙集索引。session
a.惟一索引
惟一索引是不容許其中任何兩行具備相同索引值的索引。
b.主鍵索引
數據庫表常常有一列或列組合,其值惟一標識表中的每一行,該列稱爲表的主鍵。
在數據庫關係圖中爲表定義主鍵將自動建立主鍵索引,主鍵索引是惟一索引的特定類型。該索引要求主鍵中的每一個值都惟一。數據庫設計
c.彙集索引
在彙集索引中,表中行的物理順序與鍵值的邏輯(索引)順序相同。一個表只能包含一個彙集索引。
若是某索引不是彙集索引,則表中行的物理順序與鍵值的邏輯順序不匹配。與非彙集索引相比,彙集索引一般提供更快的數據訪問速度。函數
鍵選擇原則:性能
1) 鍵設計4 原則優化
爲關聯字段建立外鍵。
全部的鍵都必須惟一。
避免使用複合鍵。
外鍵老是關聯惟一的鍵字段。
2) 使用系統生成的主鍵url
設計數據庫的時候採用系統生成的鍵做爲主鍵,那麼實際控制了數據庫的索引完整性。這樣,數據庫和非人工機制就有效地控制了對存儲數據中每一行的訪問。採用系統生成鍵做爲主鍵還有一個優勢:當擁有一致的鍵結構時,找到邏輯缺陷很容易。spa
3) 不要用用戶的鍵(不讓主鍵具備可更新性)
在肯定採用什麼字段做爲表的鍵的時候,可必定要當心用戶將要編輯的字段。一般的狀況下不要選擇用戶可編輯的字段做爲鍵。
4) 可選鍵有時可作主鍵
把可選鍵進一步用作主鍵,能夠擁有創建強大索引的能力。
索引使用原則:
索引是從數據庫中獲取數據的最高效方式之一。95%的數據庫性能問題均可以採用索引技術獲得解決。
邏輯主鍵使用惟一的成組索引,對系統鍵(做爲存儲過程)採用惟一的非成組索引,對任何外鍵列採用非成組索引。考慮數據庫的空間有多大,表如何進行訪問,還有這些訪問是否主要用做讀寫。
大多數數據庫都索引自動建立的主鍵字段,可是可別忘了索引外鍵,它們也是常用的鍵,好比運行查詢顯示主表和全部關聯表的某條記錄就用得上。
不要索引memo/note 字段,不要索引大型字段(有不少字符),這樣做會讓索引佔用太多的存儲空間。
不要索引經常使用的小型表
不要爲小型數據表設置任何鍵,假如它們常常有插入和刪除操做就更別這樣做了。對這些插入和刪除操做的索引維護可能比掃描表空間消耗更多的時間。
應該建索引的字段:1.常常做爲查詢條件的字段2.用於聯接的列(主健/外健)3.在SQL語句中常常進行GROUP BY、ORDER BY的字段;四、在常常存取的多個列上創建複合索引,但要注意複合索引的創建順序要按照使用的頻度來肯定
應該少建或者不建索引的字段有:1.表記錄太少,2.常常須要插入,刪除,修改的表,3.表中數據重複且分佈平均的字段
一些SQL的寫法會限制索引的使用:1.where子句中若是使用in、or、like、!= <>,均會致使索引不能正常使用,將"<>"換成">and<";將"is not null "換成">=chr(0)";2.使用函數時,該列就不能使用索引。3.比較不匹配數據類型時,該索引將會被忽略。
一些SQL語句優化的寫法:1.若是from是雙表的查詢時,大表放在前面,小表放在後面(基礎表)。最後面的表是基礎表。(只在基於規則的優化器中有效)2.若是三表查詢時,選擇交叉表(intersection table)做爲基礎表.(只在基於規則的優化器中有效)3.寫where條件時,有索引字段的判斷在前,其它字段的判斷在後;若是where條件中用到複合索引,按照索引列在複合索引中出現的順序來依次寫where條件;4.查詢數量較大時,使用錶鏈接代替IN,EXISTS,NOT IN,NOT EXISTS等。5.ORACLE採用自下而上的順序解析WHERE子句,那些能夠過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾.
注:缺省狀況下創建的是非簇集索引,但在如下狀況下最好考慮簇集索引,如:含有有限數目(不是不多)惟一的列;進行大範圍的查詢;充分的利用索引能夠減小表掃描I/0的次數,有效的避免對整表的搜索。固然合理的索引要創建在對各類查詢的分析和預測中,也取決於DBA的所設計的數據庫結構。索引的字段的類型也需重點考慮,字符字段索引就比數字字段索引慢得多。
備註
主鍵的命名採用以下規則:
主鍵名用pk_開頭,後面跟該主鍵所在的表名。主鍵名長度不能超過30個字符。若是過長,可對錶名進行縮寫。縮寫規則同表名的縮寫規則。主鍵名用小寫的英文單詞來表示。
外鍵的命名採用以下規則:
外鍵名用fk_開頭,後面跟該外鍵所在的表名和對應的主表名(不含t_)。子表名和父表名本身用下劃線(_)分隔。外鍵名長度不能超過30個字符。若是過長,可對錶名進行縮寫。縮寫規則同表名的縮寫規則。外鍵名用小寫的英文單詞來表示。
索引的命名採用以下規則:
1)索引名用小寫的英文字母和數字表示。索引名的長度不能超過30個字符。
2)主鍵對應的索引和主鍵同名。
3)惟一性索引用uni_開頭,後面跟表名。通常性索引用ind_開頭,後面跟表名。
4)若是索引長度過長,可對錶名進行縮寫。縮寫規則同表名的縮寫規則
index 相關語法
例:
CREATE INDEX log_url ON logaudit_log(url);
show index from logaudit_log
drop index log_request_time on logaudit_log
sql執行效率檢測 mysql explain
explain顯示了mysql如何使用索引來處理select語句以及鏈接表。能夠幫助選擇更好的索引和寫出更優化的查詢語句。
使用方法,在select語句前加上explain就能夠了:
如:explain select surname,first_name form a,b where a.id=b.id
分析結果形式以下:
table | type | possible_keys | key | key_len | ref | rows | Extra
EXPLAIN列的解釋:
table
顯示這一行的數據是關於哪張表的
type
這是重要的列,顯示鏈接使用了何種類型。從最好到最差的鏈接類型爲const、eq_reg、ref、range、indexhe和ALL
possible_keys
顯示可能應用在這張表中的索引。若是爲空,沒有可能的索引。能夠爲相關的域從WHERE語句中選擇一個合適的語句
key
實際使用的索引。若是爲NULL,則沒有使用索引。不多的狀況下,MYSQL會選擇優化不足的索引。這種狀況下,能夠在SELECT語句中使用USE
INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引
key_len
使用的索引的長度。在不損失精確性的狀況下,長度越短越好
ref
顯示索引的哪一列被使用了,若是可能的話,是一個常數
rows
MYSQL認爲必須檢查的用來返回請求數據的行數
Extra
關於MYSQL如何解析查詢的額外信息。將在表4.3中討論,但這裏能夠看到的壞的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,結果是檢索會很慢
extra列返回的描述的意義
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
這個鏈接類型使用索引返回一個範圍中的行,好比使用>或
FAQ
1
表中包含 10 萬條記錄,有一個 datetime 類型的字段。
取數據的語句:
SELECT * FROM my_table WHERE created_at < '2010-01-20';
用 EXPLAIN 檢查,發現 type 是 ALL, key 是 NULL,根本沒用上索引。
能夠肯定的是,created_at 字段設定索引了。
什麼緣由呢?
用 SELECT COUNT(*) 看了一下符合 WHERE 條件的記錄總數,竟然是 6W 多條!!
難怪不用索引,這時用索引毫無心義,就好像 10 萬條記錄的用戶表,有個性別字段,不是男就是女,在這種字段設置索引是錯誤的決定。
稍微改造一下上述語句:
SELECT * FROM my_table WHERE created_at BETWEEN '2009-12-06' AND '2010-01-20';
這回問題解決!
符合條件的記錄只有幾百條,EXPLAIN 的 type 是 range,key 是 created_at,Extra 是 Using where 。
本身總結個準則,索引的目的就是儘可能縮小結果集,這樣才能作到快速查詢。
6萬條記錄符合條件,已經超出總記錄數的一半,這時索引已經沒有意義了,所以 MySQL 放棄使用索引。 這與設置 gender 字段,並加上索引的狀況類似,當你要把全部男性記錄都選取出來,符合條件的記錄數約佔總數的一半,MySQL 一樣不會使用這個索引。 惟一值越多的字段,使用索引的效果越好。 設置聯合索引時,惟一值越多的,越應該放在「左側」。