44 | 答疑文章(三):说一说这些好问题
44 | 答疑文章(三):说一说这些好问题
讲述:林晓斌
时长16:21大小14.98M
join 的写法
Simple Nested Loop Join 的性能问题
distinct 和 group by 的性能
备库自增主键问题
小结
上期问题时间
赞 36
提建议
精选留言(57)
- 玉哥2019-02-25老师,BNl算法,如果where条件中有驱动表的过滤条件,也不会在join时候全部载入内存吧?
作者回复: 对,驱动表现过滤,然后进join buffer
34 - 龙文2019-02-23老师你好,我在第21讲求助了一个死锁问题,当时你回复说后面会解答,不过我浏览了下后续文章没找到解答,所以再次求助下。ps:用的阿里云的rds,提了工单没效果啊 作者回复: 有的,你看一下第40篇 “insert 唯一键冲突”这一段 ps:我已经离开阿里云挺久的了 😆 --------------------------------------------- 谢谢老师,我看了第40篇,还是有地方不太明白,再打扰下 mysql 版本5.6 隔离级别为rc CREATE TABLE `uk_test` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `a` int(11) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_a_b` (`a`,`b`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 表中数据: +----+---+---+---+ | id | a | b | c | +----+---+---+---+ | 1 | 1 | 1 | 2 | | 6 | 1 | 2 | 1 | +----+---+---+---+ sql:执行顺序 session1:begin; session2:begin; session1:select * from uk_test where a = 1 and b = 1 for update; session2:select * from uk_test where a = 1 and b = 1 for update; session1:insert into uk_test (a,b,c) values(1,1,2) on duplicate key update c = 2; session2:ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction 我的疑问是: 1.rc隔离级别下对唯一键的insert也会加next-key lock吗? 2.死锁日志显示 session 1已经成功加上行锁(lock_mode X locks rec but not gap), session 2在等待同一个行锁(lock_mode X locks rec but not gap waiting), session1这时因为等待lock_mode X waiting而死锁。 这里的lock_mode X waiting是指next-key lock吗? 如果是的话,没想明白这里怎么形成资源循环等待了? 我的猜测是session1 这时持有行锁,要next-key lock 所以要去加gap锁。session 2持有gap锁在等行锁。但如果是这样为什么session2 在rc下select for update,且记录存在时会加gap锁?还有gap锁加锁不是不互斥吗?展开
作者回复: 1. 会 2. 你这里 session 1 成功加锁一个record lock; session 2执行的是一个select 语句,而且a=1 and b=1就只锁一行(a,b上有联合唯一索引),这里就是要申请一个记录行锁(but not gap waiting)。 这里虽然没有加锁成功,但是已经加入了锁队列(只是这个锁是处于等待状态) ---这时候队列里面有两个锁对象了 然后session 1 再insert失败的时候,就要加next-key lock,(注意这个锁对象跟第一个锁对象不同)。 然后死锁检测看到,2号锁在等1号锁;3号要等2号,而3和1又是同一个session,就认为是死锁了。
共 10 条评论29 - 还一棵树2019-02-26看到 BNL 算法,你就应该知道这条语句的执行流程其实是这样 文章中的流程是写错了?还是我理解的有问题 1、如果是a表数据放入join buffer,根据b的每一条记录去判断是否在a中 如果在则保留记录 这个更像是b left join a。 而不是a left join b 2、如果按照这个流程,比如a里面有2行重复的数据, 如果拿b的数据在a中判断,存在则保留,那结果集只有一条数据, 而按照a left join b 会出现2条结果的展开
作者回复: “如果按照这个流程,比如a里面有2行重复的数据, 如果拿b的数据在a中判断,存在则保留,那结果集只有一条数据,” 不会呀,你看它是这样的: 假设join buffer中有两个行1 然后被驱动表取出一个1, 跟join buffer中第一个1比较,发现满足条件,放到结果集; 跟join buffer中第二个1比较,发现满足条件,放到结果集; 是得到两行的
23 - Dovelol2019-02-25老师,看评论包括您的回复说“ left join 后加上 where 的话, 肯定会被优化器优化成 join where 的形式, 那是否下次写 left join ..where 的时候, 不如直接写成 join .. where”,这个也是分情况的吧比如还是文章中的2张表,select * from a left join b on(a.f1=b.f1) where (a.f2=2);/*Q5*/和select * from a join b on(a.f1=b.f1) where (a.f2=2);/*Q6*/ 这个left join和join的语意和返回结果都不一样,怎么能直接写成join呢,如果是where b.f2=xx 的where条件可以直接写成join因为根据结果是不需要left的。展开
作者回复: 嗯 我的意思是,如果where条件里面,用到了b.f2的判断,干脆就直接写成join,不需要left join了 如果业务逻辑需要left join, 就要把条件都放到on里面 业务逻辑正确性还是优先的
21 - 梦康2019-02-25😂留言的人太多,辛苦老实答疑了。虽然我的问题没能被翻牌子
作者回复: 不好意思,确实你的问题比较难一些 最近在做收尾的工作,后面一定会把问题都清理掉的哈。 你的问题质量高,是我喜欢回答的问题类型😆
16 - 大宝2019-04-06老师你好,看了你回复 @彼得.林 时说,“在线服务最好不要让索引树超过4层“;那么有没有什么好的方法或者工具可以查看当前表的层数吗?
作者回复: innblock 可以了解下😆
13 - 千木2019-02-23老师您好,join使用join_buffer和内存区别那个问题的第一点解释我还是有些纳闷,你说由于从磁盘拿数据到内存里面会导致等等的性能问题我能够理解,但是说即使使用nbl算法也会涉及到从磁盘拿数据到内存吧,所以这点导致两种算法执行差异貌似不太合理,您觉得呢?
作者回复: BNL算法拿的数据是确定的只会拿一次(遍历一遍) 而simple nested loop join是会遍历多次的
共 5 条评论13 - 白永伟2019-02-22老师,关于备库自增id我有一个问题。既然binlog不管是statement模式还是row模式,里面的insert语句跟着的自增id都是固定的。那假如发生主备切换,备库变成主库后,客户端往新主库里插入数据时,自增id的起始值是多少,有没有可能跟已有的记录id冲突?尤其是备库还没有处理完同步过来的binlog就开始接受客户端请求时。如果要求备库必须处理完binlog才能接受客户端请求,那么怎么保证主备切换的过程中,不影响用户使用。谢谢。
作者回复: “自增id的起始值是多少,有没有可能跟已有的记录id冲突?” 如果没有主备延迟就不会出现; “尤其是备库还没有处理完同步过来的binlog就开始接受客户端请求时。” , 对,这种情况就会。 “如果要求备库必须处理完binlog才能接受客户端请求,那么怎么保证主备切换的过程中,不影响用户使用” 一般都是有这个要求的。要尽量减少影响,就是控制主备延迟。
共 2 条评论10 - 彼得.林2019-03-16不知道老师还会不会回复问题: b+树索引结构的层次和表数据量的关系是怎么样的?也就是说15万的数据量是三层结构?达到多少数据量是四层次? 一般在线服务中一个表的数据量一般多大合适?
作者回复: 你可以这么理解, N层放不下的时候,就增加一层来放。 这个行为是由页分裂触发的 在线服务最好不要让索引树超过4层
共 3 条评论9 - yhui2019-08-23我真的很迫切需要你的帮助,我是台湾人,遇到一个很神奇的问题 where in a(1,2,3,5,7,8,9) and b in(3) and c in(1,2) order by id desc 我建了一个abc联合索引,发现这语句尽然没用上联合索引 很奇怪,in里删一两个值又能选对索引,这in有什么规律 奥秘吗?多谢指点,我邀请我同事都买了你的课程
作者回复: 你可否把表结构、插入数据语句都贴一下? 就是有没有稳定的复现方法(带上MySQL版本号)
共 2 条评论5 - 钱2019-08-10这篇答疑很实用呀!第一个问题之前也发现有这样的现象,不过解释不清楚为什么,不过按照自己想要的也算使用对了left join 。 感谢老师,专栏接近尾声,现在回想一下,确实增加了不少见识,不过由于记忆不太好,加之有些知识消化的不好有些已经模糊啦😄 第一遍结束,再来第二遍,把实验都操作操作,应该会好一些。 感谢😊展开2
- 阿甘2022-01-10老师,请教一下对于in语句导致的SQL超长有没有比较好的解决方案?特别是多个in有and/or关系的情况。1
- 一只独立特行的猪2020-06-13顺序扫描表b,对于每一行数据,判断join条件(也就是(a.f1=b.f1)and(a.f1=1))是否满足... 这里的 条件 a.f1 = 1 是认真的吗?没有写错吗?共 1 条评论2
- Jie2020-03-21这里图2里面的join条件是a.f1 = 1,不是上面文字里的a.f2=b.f2呀,是因为编辑过了么?2
- Chris2019-03-15这两天在线上遇到一个比较诡异的事情,突然有几分钟连不上MySQL,通过error日志和监控的processlist显示,MySQL把很多链接都kill掉了,但处于sleep状态和show status的语句没有kill,看监控的资源使用情况不是很高,只是innodb rows read指标特别高,现在完全是没头绪了
作者回复: 看看是不是有什么外部工具在工作
1 - 龙文2019-02-24明白了 谢谢老师!
作者回复: 👍
1 - 龙文2019-02-23老师你好,我在第21讲求助了一个死锁问题,当时你回复说后面会解答,不过我浏览了下后续文章没找到解答,所以再次求助下。ps:用的阿里云的rds,提了工单没效果啊
作者回复: 有的,你看一下第40篇 “insert 唯一键冲突”这一段 ps:我已经离开阿里云挺久的了 😆
1 - 夜空中最亮的星2019-02-22这么快就要结束,好快啊
作者回复: 跟进得很快啊大家😆
1 - 万勇2019-02-22感谢老师上一期的解答,还请教一个分区表的问题,分区表创建的聚集索引是分区本地维护的吧,但是主键索引要保证全局唯一性。那分区和主键索引之间是不是要建立一种关系?另外分区表如果我们创建普通索引,按道理可以分区创建的,分区维护自己的普通索引,各分区之间互不影响。
作者回复: 就是我这篇末尾建议的几种建表方法,就是建立联系了
1 - let_me_go2022-11-15 来自浙江BNL和Simple Nested Loop Join的区别:BNL使用了join buffer来存驱动表,BNL没有。BNL是顺序扫描被驱动表,然后取出每条数据去看驱动表有没有匹配的【驱动表再join buffer中】,理想情况下只需要扫描一次。Simple Nested Loop Join 顺序扫描驱动表,然后去被驱动表看有没有匹配的,会多次扫描被驱动表。而被驱动表又存储在磁盘中,每次扫描读取数据代价都比较高