11 | 怎么给字符串字段加索引?

维护邮箱登录系统,用户表

mysql> select  f1, f2 from SUser where email='xxx';    email 没有索引,全表扫描。

创建索引的语句不指定前缀长度,索引就会包含整个字符串。

mysql> alter  table SUser add index index1(email);          //含整个字符串

mysql> alter  table SUser add index index2(email(6));      //只取前 6 个字节

数据结构和存储区别

图 1 email 索引结构
图 2 email(6) 索引结构

一、前缀索引

占用空间小,可能会增加额外的记录扫描次数。

select  id,name,email from SUser where email='zhangssxyz@xxx.com';

index1执行顺序:

1.  从 index1 索引树找到满足索引值是’zhangssxyz@xxx.com’的这条记录,取得 ID2 的值;

2.  查主键值=ID2 行, email 值正确,行记录加入结果集;

3.  取 index1 索引树上刚刚查到的位置的下一条记录,发现已经不满足email='zhangssxyz@xxx.com’的条件了,循环结束。

回主键索引取一次,系统认为扫描一行

index2执行顺序:

1.  从 index2 索引树找到满足索引值是’zhangs’的记录,找到第一个 ID1

2.  查到主键=ID1 行,查出 email 的值不是’zhangssxyz@xxx.com’丢弃

3.  index2 下一条,这次值对了加入结果集

4. 重复上一步,idxe2 不是’zhangs’时,循环结束。

回主键索引取 4 次数据(index2要回索引),扫描了 4 行。导致查询次数多。

如果定义index2 不是 email(6) 而是 email(7),前缀’zhangss’只有一个,直接查到 ID2。

前缀索引,定义好长度,节省空间,不用增加太多查询成本。

二、多长前缀好

建立索引时关注区分度,区分度越高,重复键值越少。多少个不同的值,判断用多长前缀:

mysql> select  count(distinct email) as L from SUser;  

选取不同长度的前缀来看这个值,看 4~7 个字节的前缀索引

mysql> 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,

from SUser;

前缀索引很可能会损失区分度,设定可以接受的损失比例,比如 5%。 L4~L7 中,找出不小于 L * 95% 值,假设L6、L7 都满足,选择前缀长度为 6

三、前缀索引对覆盖索引的影响

增加扫描行数,不止影响性能。

select id,email  from SUser where email='zhangssxyz@xxx.com';  只返回 id 和 email 字段。

用 index1可用覆盖索引,直接返回,不回ID 索引。index2( email(6) )的话,回 ID 索引,再判断 email 字段值。系统并不确定是否截断完整信息。

前缀索引就用不上覆盖索引对查询性能的优化

邮箱效果不错。但公民信息系统,身份证号12 以上前缀索引,满足区分度

占用空间越大,数据页索引值就越少,搜索效率越低。

四、占用空间小,效率高

4.1 倒序存储

身份证号倒过来存,每次查询的时候:

mysql> select  field_list from t where id_card = reverse('input_id_card_string');

最后 6 位。不要忘记用count(distinct)验证

4.2 hash 字段

创建整数字段,保存身份证校验码(创建索引)。

mysql> alter  table t add id_card_crc int unsigned, add index(id_card_crc);

插入同时用 crc32()函数得到校验码填到新字段。可能存在冲突,不同身份证号 crc32() 结果相同,where 判断 id_card 值是否精确相同

mysql> select  field_list from t where id_card_crc=crc32('input_id_card_string') and  id_card='input_id_card_string'

索引长度4 字节,比原来小。

相同:

不支持范围查询。倒序存储的字段上创建的索引是按照倒序字符串的方式排序的,已经没有办法利用索引方式查出身份证号码在 [ID_X, ID_Y]的所有市民了。hash 只支持等值查询。

区别:

1. 占用额外空间:倒序:存储主键索引上,不消耗额外空间, hash 增加一个字段。倒序存储方式 4 字节不够,消耗差不多抵消

2. CPU 消耗:倒序:写和读的时候,额外调用reverse 函数hashcrc32() 函数。reverse 消耗 CPU 资源小。

3. 查询效率hash 稳定,冲突概率小。倒序存储:前缀索引的方式,增加扫描行数。

小结

字符串字段创建索引场景,使用方式:

1.  完整索引,占用空间;

2.  前缀索引,节省空间,增加查询扫描次数,不能用覆盖索引;

3.  倒序存储,再创建前缀索引,用于绕过字符串本身前缀的区分度不够问题;

4.  hash 字段索引查询性能稳定,有额外存储、计算消耗不支持范围扫描(跟第三种一样)。

问题

维护学生信息数据库,登录名”学号 @gmail.com",学号:15位数字,城市编号(3)、学校编号(4、6)、入学年份(1~10)、顺序编号(后5)。

只考虑登录验证,怎么设计登录名索引?

正、反向,重复度都高。入学年份+顺序编号(9)

在此基础上,数字类型存。201100001,占 4 个字节。就是一种 hash,字符串转数字

评论1

学校每年预估2万新生,50年才100万记录,直接全字段索引

hash索引适合,登录检验,不需范围查询。倒序索引,区分度没前缀高。

评论2

学号用bigint存储,4个字节,比前缀索引占用要小。比hash索引,有区间查询的优势

评论3

表数据量特别大:

字符串字段进制压缩,限制每个字符范围(如字母数字下划线)。

每个字节并没存8 bit信息量。单个字符取值只有n种可能性(把字符转成0到n-1的数字),把n进制转为为更高进制存储(ascii可看做是128进制)。

减少索引长度,兼顾前缀匹配

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容