問題sql
索引能夠加快查詢速度,那麼是否是表都須要創建索引呢?
spa
1、表記錄比較少時,不必創建索引。
.net
2、索引的選擇性比較低時,不必創建索引。code
索引的選擇性是指不重複的索引值與表記錄數的比值。
blog
索引的選擇性的取值範圍爲(0,1】,選擇性越高的索引價值越大。
索引
如:MySQL示例庫的titles表,看一下它的選擇性:get
SELECT COUNT(DISTINCT(title))/COUNT(1) AS Selectivity FROM titles;
title的選擇性爲0.0000,因此沒有必要爲其單獨建索引。
it
3、前綴索引
ast
前綴索引是用列的前綴代替整個列做爲索引key,當前綴長度合適時,能夠作到既使得前綴索引的選擇性接近全列索引,同時由於索引key變短而減小了索引文件的大小和維護開銷。
class
下面以employees表爲例介紹前綴索引的選擇和使用。
SELECT * FROM employees WHERE first_name='Eric' AND last_name='Anido';
執行上面的SQL,時間爲0.235s。
上面的SQL查詢查詢計劃,能夠看出,type爲ALL,也就是全表掃描。
建<first_name>或<first_name,last_name>,看下兩個索引的選擇性:
SELECT COUNT(DISTINCT(first_name))/COUNT(1) AS Selectivity FROM employees; SELECT COUNT(DISTINCT(CONCAT(first_name, last_name)))/COUNT(1) AS Selectivity FROM employees;
2句SQL的結果分別爲0.004二、0.9313。<first_name,last_name>索引的選擇性很好,可是長度爲30,有沒有兼顧長度和選擇性的辦法呢?也就是能夠考慮用first_name和last_name的前幾個字符創建索引,看一下選擇性是多少:
SELECT COUNT(DISTINCT(CONCAT(first_name, LEFT(last_name, 3))))/COUNT(1) AS Selectivity FROM employees; SELECT COUNT(DISTINCT(CONCAT(first_name, LEFT(last_name, 4))))/COUNT(1) AS Selectivity FROM employees;
查詢2個SQL的結果分別爲0.787九、0.9007,明顯第二句SQL的選擇性高出不少。
咱們來創建索引:
ALTER TABLE employees ADD INDEX `first_name_last_name4` (first_name, last_name(4));
查詢前面的SQL語句,執行時間爲0.002。查詢效率已經很明顯了。
總結:
前綴索引兼顧索引大小和查詢速度,可是其缺點是不能用於ORDER BY和GROUP BY操做,也不能用於Covering index(即當索引自己包含查詢全部需所有數據時,再也不訪問數據文件自己)。