MySQL 索引選擇性與前綴索引(示例庫)

問題sql

索引能夠加快查詢速度,那麼是否是表都須要創建索引呢?
spa

MySQL 索引選擇原則分析(一)中已經介紹了,索引文件是存儲在磁盤上的。所以索引雖然加快了查詢速度,可是索引也是有代價的。

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(即當索引自己包含查詢全部需所有數據時,再也不訪問數據文件自己)。

相關文章
相關標籤/搜索