如何给特殊字符串加索引:如身份证、邮箱等
-
1 建表語句
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`id_card` varchar(18) NOT NULL,`email` varchar(50) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDBINSERT INTO `test`.`user`(`id`, `id_card`, `email`) VALUES (1, '321023199303164012', 'wangheling@163.com'); INSERT INTO `test`.`user`(`id`, `id_card`, `email`) VALUES (2, '321023199003184012', 'wangwu@163.com'); INSERT INTO `test`.`user`(`id`, `id_card`, `email`) VALUES (3, '321023199003251234', 'wangsan@sina.com'); INSERT INTO `test`.`user`(`id`, `id_card`, `email`) VALUES (4, '021236199503251235', 'wangsi@163.com');user表使用郵箱作為登錄賬號。
2 郵箱字段建立索引
這里我們用登錄賬號,也就是email字段作為索引。
2.1 直接給email加索引
select * from user where email = 'wangheling@163.com'2.1.1 執行流程
因為葉子節點存放的就是email的完整值,在非聚集索引里根據email查到了主鍵id=1,然后進行回表,這里發生一次回表.
2.1.2 存在問題
因為郵箱較長,因為b+tree節點是按頁存取的,默認16k,如果鍵值過長,導致問題就是每頁存放的鍵值數量就較少,會增加樹高,增加IO次數。
2.2 前綴索引email(4)
select * from user where email = 'wangheling@163.com'2.2.1 執行流程
因為葉子節點只會存放email前四個字節的值,所以在非聚集索引里查到四條記錄,還要進行四次回表操作,比對email=‘wangheling@163.com’記錄進行篩選。
2.2.2 存在問題
因為email長度截取了,那么b+tree每個節點存儲鍵值數量多了,樹高就低了,那么帶來的問題就是,增加了回表的次數。
2.3 前綴索引email(6)
select * from user where email = 'wangheling@163.com'2.3.1 執行流程
因為葉子節點只會存放email前六個個字節的值,所以在非聚集索引里查到一條記錄,只要進行一次回表操作,比對email=‘wangheling@163.com’,得到結果。
2.4 階段小結
通過上面三個案例可以得到一個結論:
使用前綴索引,定義好合適的長度,可以在空間和查詢效率取得一個平衡。
那么這個前綴索引長度如何選取呢?
select count(distinct left(filed,length)) from tableName;
建立索引的原則就是選取離散度大的字段,那么我們可以計算使用多少長度離散度大:我們通過如下sql:
select count(distinct left(email,4)) as L4,count(distinct left(email,5)) as L5,count(distinct left(email,6)) as L6,count(distinct left(email,7)) as L7,count(distinct left(email,8)) as L8 from user;結果如下:
可以看到當長度為6時,區分度最大,可以email(6)。2.5 前綴索引帶來其他性能問題
比如:
select id, email from user where email = 'wangheling@163.com';上面這個sql,當我們沒有使用前綴索引,利用了覆蓋索引,無需回表,而如果使用了前綴索引,因為葉子節點沒有保存完整的email信息,那么會進行回表。
當我們使用前綴索引,就是利用不到覆蓋索引,需要回表,所以得根據業務場景來選擇是否使用前綴索引。
3 身份證字段建立索引
身份證長度為18,不適合作為索引。身份證號碼特點:前6位代表地址,中間8位為年月日。
3.1 前綴索引
前面談到前綴索引,就不說了。這里存在問題就是,當維護系統是一個市政系統,因為前6位區分度就不高了,所以需要截取長度要更長,還是浪費空間。
3.2 倒序存儲
因為身份證后六位區分度高,那么我們可以將身份證倒序存儲,然后索引為id_card(6)
select * from user where id_card = reverse('輸入的正序身份證號碼');倒序存儲只適用等值查詢。
3.3 哈希
可以新增一個字段存儲身份證號碼的哈希值,加上索引,存入身份證時候,對身份證進行crc3()計算,得到的值存入id_card_crc,索引長度為4,因為hash可能會發生碰撞,所以查詢時候加上身份證作為篩選條件:
select * from user where id_card_crc = crc32("輸入的身份證號碼") and id_card = '輸入身份證號';哈希存儲只適用等值查詢。
3.4 身份證號碼拆分存儲
可以將區分度高的,比如后六位單獨存儲。
4 總結
對于長度較長的字符串,我們可以這么建立索引:
- 前綴索引
- 倒序存儲
- 哈希存儲
- 字段拆分
總結
以上是生活随笔為你收集整理的如何给特殊字符串加索引:如身份证、邮箱等的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STK简介
- 下一篇: 盛大bambook锦书十分钟应用评述