Mysql可以使用字符串前綴 作為索引 以節約空間。
下面我們以 Java的UUID 生成的 32位(移除UUID中的 中划線)字符串 來做一下 測試。
表結構:
CREATE TABLE `test_uuid` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `uuid` varchar(36) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT DEFAULT CHARSET=utf8
UUID生成的方式(不考慮replaceAll的替換效率):
UUID.randomUUID().toString().replaceAll("-", "")
查詢 不同長度的前綴索引效率(索引的選擇性,即不重復的索引值)的SQL:
select count(DISTINCT uuid) / count(*) as total, count(DISTINCT LEFT(uuid,5)) / count(*) as five, count(DISTINCT LEFT(uuid,6)) / count(*) as six, count(DISTINCT LEFT(uuid,7)) / count(*) as seven, count(DISTINCT LEFT(uuid,8)) / count(*) as eight, count(DISTINCT LEFT(uuid,9)) / count(*) as nine, count(DISTINCT LEFT(uuid,10)) / count(*) as ten from test_uuid;
下面看一下測試數據及結果:
20W數據

40W

60W

80W

100W

200W
300W

500W

1000W

2000W
隨着數據量的增多,同樣長度的前綴索引選擇性 逐漸降低。
前7位 在2000W數據的時候損失了 0.04, 也就是說 每100 條數據, 會有4條與其他96條數據 有重復。
前9位 在2000W數據的時候損失了 0.0001 ,也就是說 每10000 條數據,會有1 條與 其他 9999條有重復。
前10位 在2000W數據的時候 選擇行 依然為1 (前10位沒有任何重復的)。
大家可以算一下 26的10次方,大概是 141 萬 億。
當然,以上數據 我只做過一次, 其他測試數據應該與 本次測試數據 稍有不同,但可以肯定的是:不會相差很多。
所以,當業務需要使用 uuid 作為 業務唯一的key時, 可以評估業務數據量,選擇合適長度的前綴索引。
前綴索引的選擇性 越接近 總長度索引的選擇性 時,說明已經可以了。
但是,前綴索引有一些缺點:
1. Mysql 前綴索引 不支持 order by 和 group by 查詢。
2 Mysql 前綴索引 不能作為 覆蓋索引使用。
各位大佬有問題,歡迎交流。
