MySql 中使用 or 条件会走索引吗?
MySql 版本5.6
MySql 版本5.6
1、 a 是索引,b 不是
● 在 InnoDB 中,MySql 全表扫描,不走索引
我们思考下,如果 MySql 走索引 a,由于b不是索引,需要全表扫描,最后还需要merge求并集。结果就是:索引扫描 + 全表扫描 + merge 处理。如果是你,你愿意全表扫描还是走索引?
2、 a 和 b 都是索引
● 在 InnoDB 中,MySql 走索引
我们可以看到,当 a,b 都是索引时,使用了索引 idx_a 和 idx_b,
type的信息:index_merge
extra中的信息:
Using union(idx_a,idx_b);Using where
3、index merge
注意:MySQL5.0之前,一个表一次只能使用一个索引,无法同时使用多个索引分别进行条件扫描。但是从5.1开始,引入了 index merge 优化技术,对同一个表可以使用多个索引分别进行条件扫描。
同一个表的多个索引的范围扫描可以对结果进行合并,合并方式分为三种:union, intersection, 以及它们的组合(先内部intersect然后在外面union)
对于 or 条件,,index uion merge 就是多个索引条件扫描,对得到的结果进行并集运算。
MySql 中的 varchar 字段是如何建立索引的?
依据《阿里巴巴》开发手册 -- MySql索引规约
●【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引
说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。
●【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可
说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分 度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度 来确定。
如果在 email 字段上建立索引:
这两种不同的定义在数据结构和存储上有什么区别呢?
index1
index2
举个栗子:
● 对于索引 index1
① 从 index1 索引树找到满足索引值是"zhangssxyz@xxx.com"的这条记录,取得 ID2 的值;
② 到主键上查到主键值是 ID2 的行,判断 email 的值是正确的,将这行记录加入结果集;
③ 取 index1 索引树上刚刚查到的位置的下一条记录,发现已经不满足email="zhangssxyz@xxx.com"的条件了,循环结束。
● 对于索引 index2
① 从 index2 索引树找到满足索引值是’zhangs’的记录,找到的第一个是 ID1;
② 到主键上查到主键值是 ID1 的行,判断出 email 的值不是’zhangssxyz@xxx.com’,这行记录丢弃;
③ 取 index2 上刚刚查到的位置的下一条记录,发现仍然是’zhangs’,取出 ID2,再到 ID 索引上取整行然后判断,这次值对了,将这行记录加入结果集;
④ 重复上一步,直到在 idxe2 上取到的值不是’zhangs’时,循环结束。
使用前缀索引后,可能会导致查询语句读数据的次数变多。如果我们定义的 index2 不是 email (6) 而是 email (7),也就是说取 email 字段的前 7 个字节来构建索引的话,即满足前缀’zhangss’的记录只有一个,也能够直接查到 ID2,只扫描一行就结束了。
如何确定字符串索引的长度?
可以使用 count(distinct left(列名, 索引长度))/count(*) 来确定,找出不小于90%的值
● 前缀索引对覆盖索引的影响
这个语句只要求返回 id 和 email 字段。
所以,如果使用 index1的话,可以利用覆盖索引,从 index1 查到结果后直接就返回了,不需要回到 ID 索引再去查一次。
而如果使用 index2(即 email (6) 索引结构)的话,就不得不回到 ID 索引再去判断 email 字段的值。
● 前缀索引区分度差
比如说身份证号,一共 18 位,其中前 6 位是地址码,所以同一个县的人的身份证号前 6 位一般会是相同的。
按照我们前面说的方法,可能你需要创建长度为 12 以上的前缀索引,才能够满足区分度要求。
但是,索引选取的越长,占用的磁盘空间就越大,相同的数据页能放下的索引值就越少,搜索的效率也就会越低。
其他解决方案:
① 倒序存储
由于身份证号的最后 6 位没有地址码这样的重复逻辑,所以最后这 6 位很可能就提供了足够的区分度。
② 使用 hash 字段。
你可以在表上再创建一个整数字段,来保存身份证的校验码,同时在这个字段上创建索引,索引的长度变成了 4 个字节,比原来小了很多。
注意:以上两种方案都有一个共同的缺点,不支持范围查找。我们需要具体情况具体分析。
MySql分页limit速度太慢优化方法
● 常用的 limit 用法
offset 是偏移量,默认是 0,rows 指预期检索的行数
如果 offset = 1000000 ,rows = 10 时,意味着扫描符合条件的 1000010 行,只要最后 10 行记录。
《阿里巴巴手册》中对 MySql 分页做了如下说明:
●【推荐】利用延迟关联或者子查询优化超多分页场景
说明:
MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。
正例:
先快速定位需要获取的 id 段,然后再关联:
SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20) b where a.id=b.id
● 解决 limit 分页常用方案
如果之前有关注 Python大星的老铁们,应该看过一篇文章
,我们从头条文章分页接口可“管中窥豹”。
① 每次取出最大时间 max_behot_time
② 给 max_behot_time 加上索引
如果能使用覆盖索引,可以建立联合索引,避免回表查询
Python大星 曾去京东面试
有一道 MySql 的面试题留下深刻的印象
题意大致如下:
假设有一个软件,每次用户开机会提示“你打败了全国电脑 **% 的电脑”,如果是你,你会怎么设计MySql 数据库(考虑大数据量的情况)
欢迎各位老铁踊跃发言
没错,说的就是你!!!
>>>
声明:我要去上班所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,版权归原作者所有,原文出处。若您的权利被侵害,请联系删除。
本文标题:(python画派大星)(python派大星的颜色)
本文链接:https://www.51qsb.cn/article/4094.html