发布日期:2023-10-30 06:11 点击次数:53
[[440636]]开云百家乐
本文转载自微信公众号「飞天小牛肉」,作家小牛肉。转载本文请筹商飞天小牛肉公众号。
前缀索引并不是一个难通晓的东西,然而这内部波及到的一些细节,我信托好多同学王人莫得去潜入了解过。
老章程,前缀索引关联口试题的背诵版在文末。点击阅读原文不错直达我收录整理的各大厂口试真题
InnoDB 表中每一列索引的最大长度不可杰出 767 字节,是以,关于某些相比长的字段,若是确乎有拓荒索引的必要,使用前缀索引不仅大要幸免索引长度杰出摒弃,而且相干于平日索引来说,占用的空间和查询老本更小。
至于为什么说前缀索引占用的空间和查询老本更小,咱们来径直上个例子:
假定表中存在一个邮箱 email 字段,咱们在这个字段上头分别创建平日索引和前缀索引:
皇冠客服飞机:@seo36871)平日索引,包含了每行 email 纪录的的所有这个词这个词字符串:alter table user add index index1(email);
负债2)前缀索引,取每行 email 纪录的前 6 个字节:alter table user add index index2(email(6));
分析人士认为,之所以很少见到乌军使用TOS-1A火箭炮,除了缴获数量有限外,也与其固有缺陷有关:
S-25型航空火箭弹重约480千克,不同的战斗部型号重量在150千克到190千克之间不等,无制导型号的最大有效射程为4千米,制导型号最大射程为11千米,战斗部主要分为高爆型S-25F和破片杀伤型S-25O,并发展出了多款改进型号。
你不错看到,由于 email(6) 这个索引结构中每个 email 字段王人只取前 6 个字节 zhangs,是以占用的空间比平日索引更小,这便是使用前缀索引的上风。
很好通晓,对吧。
前缀索引一宗罪然而,前缀索引这个占用空间更小的上风可能会带来异常的纪录扫描次数。
举个例子,扩张如下 sql 语句:
select 开云百家乐* from user where email = 'zhangs2001';
1)关于平日索引 email 来说,扩张规章如下:
从 index1 索引树找到第一个称心索引值是 'zhangs2001' 的这笔纪录,并获取到主键 ID2 的值; 把柄主键值回表查询,获取其他相应的纪录,然后将获取到的结果加入结果集; 取 index1 索引树上刚刚查到的位置的下一笔纪录,发现也曾不称心 email='zhangs2001' 的条目了,完毕扩张这个流程中,只需要回表一次
2)关于前缀索引 email(6) 来说,扩张规章如下:
从 index1 索引树找到第一个称心索引值是 'zhangs' 的这笔纪录,并获取到主键 ID1 的值; 把柄主键值回表查询,判断 email 的值到底是不是 'zhangs2001',发现并不是,这行纪录丢弃 取 index1 索引树上刚刚查到的位置的下一笔纪录,发现 email 前缀仍然称心 'zhangs',则获取到主键 ID2 的值;然后把柄主键值回表查询,返现 email 的值确乎是 'zhangs2001',则将这行纪录加入结果集 如斯重叠,直到 email 前缀不再是 'zhangs',则扩张完毕不错看到,这个流程中,需要回表四次
这便是前缀索引的第一宗罪:使用前缀索引可能会加多纪录扫描次数与回表次数,影响性能
不外呢,咱们作念一些微弱的改换,就能让这个前缀索引回表次数大大减少。
把 index2-email(6) 这个前缀索引改成 index3-email(7):
再来看上头这个例子,扩张规章如下:
从 index1 索引树找到第一个称心索引值是 'zhangs2' 的这笔纪录,并获取到主键 ID2 的值; 把柄主键值回表查询,判断 email 的值到底是不是 'zhangs2001',发现确乎是,则将这行纪录加入结果集 取 index1 索引树上刚刚查到的位置的下一笔纪录,发现 email 前缀不称心 'zhangs2',则扩张完毕不错看到,相干于平日索引,email(7) 这个前缀索引不异只需要回表一次,何况占用更少的索引空间。
前缀索引二宗罪看底下这条 SQL 语句:
皇冠博彩中,只有赛事了如指掌,才能制定更加精确投注策略。select id,email from user where email = 'zhangs2001';
若是使用 index1 索引(即 email 所有这个词这个词字符串的索引结构)的话,不错期骗上笼罩索引,从 index1 索引树上查到结果后就不错复返了,不需要进行回表。
皇冠网官网而若是使用 index2(即 email(6) 前缀索引结构)的话,欧博代理开户就不得不再次把柄主键值去回表判断 email 字段的值是否确切是 'zhangs2001'。也便是说,使用前缀索引就用不上笼罩索引对查询性能的优化了。
那有同学就要问了,若是是 email(10) 呢,这个前缀索引不就统统包含了 zhangs2001 的所有这个词信息了嘛,还需要回表吗?
谜底是并不可休止 InnoDB 的回表,因为 InnoDB 并不可详情前缀索引的界说是否截断了完好信息。谁知说念你会不会又加多一个 'zhangs20012' 的纪录呢,对吧。
澳门太阳城赌场若何界说前缀索引的长度
皇冠博彩索引考取的越长,占用的磁盘空间就越大,计划的数据页能放下的索引值就越少,搜索的效果也就会越低。
在上头的例子中咱们提到,只需要把前缀索引从 email(6) 改成 email(7),就不错大大减少纪录扫描和回表的次数,是以,在界说前缀索引的时期,咱们需要在占用空间和搜索效果之间作念一个衡量 trade-off。
事实上,咱们在拓荒前缀索引时宥恕的是分辩度,分辩度越高,意味看守叠的键值越少,是以分辩度越高越好。
关于索引来说,什么是分辩度呢,很浅薄,便是这个索引上有些许个不同的值。拓荒出来的索引上领有越多不同的值,那么这个索引的分辩度就越高。
因此,咱们不错通过统计索引上有些许个不同的值来判断要使用多长的前缀。不错使用底下这个语句,缱绻出 email 列上有些许个不同的值,记作 email_length:
皇冠体育网上投注平台select count(distinct email) as email_length from user;
然后,挨次考取不同长度的前缀来看分辩度,比如咱们要看前缀索引的长度是 6~10 时期的分辩度,不错用这个语句:
幸运快艇电子游戏select count(distinct left(email,6))as email_length_6, count(distinct left(email,7))as email_length_7, count(distinct left(email,8))as email_length_8, count(distinct left(email,9))as email_length_9, count(distinct left(email,10))as email_length_10, from user;
虽然了,既然咱们使用了前缀索引,那么就不可幸免的会失掉分辩度,就像咱们前边所说的,谁也不知说念会不会又新增出一笔纪录统统踩中前缀然而又不称心判断条目。是以咱们需要事先设定一个不错招揽的分辩度失掉比例,比如 5%。然后找出不小于 email_length * (1 - 5%) 的值,假定这里 email_length_8、email_length_9 王人称心,咱们就不错遴荐前缀长度为 8。
前缀索引的分辩度不够高奈何办我其时实习的时期就遭遇过这个问题,字段(假定这个字段名是 a)超等超等长,精深于 InnoDB 的摒弃 767 字节,平日索引服气是不可能了,前缀索引就算是长度界说成 767 王人照旧存在分辩度不高的情况,然而又存在把柄这个字段进行查询的挺常常的一个需求。
一个很常见的处分技巧便是 Hash。
对这个超长字段 a 进行 hash(假定定名为 a_hash) 存入数据库,然后对这个 hash 值拓荒索引,由于 hash 值不异可能存在破损,也便是说两个不同的 a 通过 Hash 函数得到的结果可能是计划的,是以咱们在查询语句的 where 部分还需要进行一次精准判断
# 假定输入的字段是 input_a select * from user where hash(input_a) = a_hash and input_a = a;
不外使用 Hash 这种面孔有个人所共知的弊端,那便是不支撑鸿沟查询了,只可等值查询。
临了放上这说念题的背诵版:
口试官:前缀索引了解吗,为什么要建前缀索引
小牛肉:前缀索引便是考取字段的前几个字节拓荒索引。领先,InnoDB 摒弃了每列索引的最大长度不可杰出 767 字节,是以,关于某些相比长的字段,若是确乎有拓荒索引的必要,使用前缀索引不仅大要幸免索引长度杰出摒弃,而且相干于平日索引来说,占用的空间和查询老本更小。
不外前缀索引可能会导致两个问题:
第一个,使用前缀索引可能会加多纪录扫描次数与回表次数,影响性能。针对这少量呢,其实前缀索引长度的考取照旧很伏击的,可能前缀界说的长少量,就大要大幅减少纪录扫描次数和回表次数,是以,在拓荒前缀索引的时期,咱们需要在占用空间和搜索效果之间作念一个衡量
第二个,使用前缀索引其实就没法用笼罩索引对查询性能的优化了,因为 InnoDB 并不可详情前缀索引的界说是否截断了完好信息,就算是统统踩中了前缀索引,InnoDB 还获取表阐述一次到底是不是称心条目了。