索引首碼 使用 字元串列的索引規範中的語法,您可以創建僅使用列首字元的索引 。以這種方式僅索引列值的首碼可以使索引文件小得多。為a 或 column 編製索引時 , 必須為索引指定首碼長度。例如: col_name(N)NBLOBTEXT CREATE TABLE test (blob_col BL ...
索引首碼
使用 字元串列的索引規範中的語法,您可以創建僅使用列首字元的索引 。以這種方式僅索引列值的首碼可以使索引文件小得多。為a 或 column 編製索引時 , 必須為索引指定首碼長度。例如: col_name(N)NBLOBTEXT
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
首碼最長可以為1000個位元組(InnoDB表中為767個位元組 ,除非已 innodb_large_prefix設置)。
註意 首碼限制以位元組為單位,而在首碼長度CREATE TABLE, ALTER TABLE和 CREATE INDEX語句被解釋為非二進位串類型的字元數(CHAR, VARCHAR, TEXT對於二進位串類型),並且位元組數(BINARY, VARBINARY, BLOB)。為使用多位元組字元集的非二進位字元串列指定首碼長度時,請考慮到這一點。
如果搜索詞超過索引首碼長度,則使用索引排除不匹配的行,然後檢查其餘行是否可能匹配。
當要索引的列字元很多時 索引則會很大且變慢
( 可以只索引列開始的部分字元串 節約索引空間 從而提高索引效率 )
原則: 降低重覆的索引值
例如現在有一個地區表
area | gdp | code |
---|---|---|
chinaShanghai | 100 | aaa |
chinaDalian | 200 | bbb |
usaNewYork | 300 | ccc |
chinaFuxin | 400 | ddd |
chinaBeijing | 500 | eee |
發現 area 欄位很多都是以 china 開頭的
那麼如果以前1-5位字元做首碼索引就會出現大量索引值重覆的情況
索引值重覆性越低 查詢效率也就越高
首碼索引測試
// 創建一個測試表
CREATE TABLE `x_test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`x_name` varchar(255) NOT NULL,
`x_time` int(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4145025 DEFAULT CHARSET=utf8mb4
// 添加200萬條測試數據
INSERT INTO x_test(x_name,x_time) SELECT CONCAT(rand()*3300102,x_name),x_time FROM x_test WHERE id < 30000;
1.在無任何索引的情況下隨便查詢一條
SELECT * FROM x_test WHERE x_name = '1892008.205824857823401.800099203178258.8904820949682635656.62526521254';
查詢時間:2.253s
2.添加首碼索引 ( 以第一位字元創建首碼索引 )
alter table x_test add index(x_name(1))
再次查詢相同sql語句
SELECT * FROM x_test WHERE x_name = '1892008.205824857823401.800099203178258.8904820949682635656.62526521254';
查詢時間:3.291s
當使用第一位字元創建首碼索引後 貌似查詢的時間更長了
因為只第一位字元而言索引值的重讀性太大了
200萬條數據全以數字開頭那麼平均20萬條的數據都是相同的索引值
3.重新建立首碼索引 這次以前4位字元來創建
alter table x_test add index(x_name(4));
再次查詢相同sql語句
SELECT * FROM x_test WHERE x_name = '1892008.205824857823401.800099203178258.8904820949682635656.62526521254';
查詢時間:0.703s
這次以前4位創建索引 大大減少了索引值的重覆性 查詢速度從3秒提升到0.7秒
4.200萬條數據都以數字開頭 而0-9排列組合7位則可達到千萬種組合
也就是以前7位來做索引則不會出現重覆索引值的情況了
alter table x_test add index(x_name(7));
再次查詢相同sql語句
SELECT * FROM x_test WHERE x_name = '1892008.205824857823401.800099203178258.8904820949682635656.62526521254';
查詢時間:0.014s ( 首次執行無緩存狀態下 )
參考:
https://dev.mysql.com/doc/refman/5.7/en/column-indexes.html
https://www.jianshu.com/p/fc80445044cc