本文正在参加「技术专题19期 漫谈数据库技术」活动
不论这么聊这个话题,查询最终的目的始终是获取最终的结果,但是在sql当中往往有多种方式可以得到同样的结果,那么这样就衍生出一个问题,到底那个结果是最优的,之前讨论过在查询过程当中使用limit,少全表查询,但是不单单是这样,遇到不同的案例,要有不同的思考,今天就聊一聊分解关联查询。
回忆
在之前的工作当中,除了感觉自己写的sql查询速度慢之外,其实有时候也感觉不够高级,当时理解的所谓的高级就是复杂,感觉写一条长长的sql,通过各种连接查询实现了查询效果是一件很酷的事情,但是在一次操作当中被大佬上了一课,才明白,关联查询不一定是一个好的结果,先大概的回忆一些当时的案例:
但是是要对一个多对多的模型进行查询,大概记得是一个类似角色和权限的查询吧(因为当时在做BIM管理平台),数据库的业务逻辑是一个角色可以拥有多种权限,一种权限可以被多个角色拥有。当然数据表是三张:
1、role 角色表,大致记录着 角色id,角色名称等字段。
2、permission 权限表,大致记录着权限id,权限描述等字段。
3、ro_per 角色权限表,嘿嘿嘿,由于是回忆,这里表名有点粗糙了,记录着id,role_id和per_id
然后查询角色拥有的权限,就写了下面的联查语句:
select role.id,role.role_name,permission.per_name from role
join ro_per on ro_per.role_id = role.id
join permission on ro_per.per_id = permission.id
where role.role_name="项目负责人";
当然也查到了结果
id role_name per_name
2 项目负责人 项目创建权限 2 项目负责人 模块创建权限
然后我就去找带我的老大哥邀功:大哥,您看,查出来了。大哥扫了一眼,点了点头:嗯,琢磨一些拆开写可不可以?,比如这样:
select id,role.role_name from role where role_name="项目负责人";
select per_id from ro_per where id = 2;
select per_name from permission where id in (1,2);
思考
嗯哼,当时我有点不理解,这个写法好像在学习那会儿就不想写了,但是也不好意思直接说,然后就假装琢磨,然后开始摸鱼,嘿嘿嘿,老大哥有点看不下去,但是也没有多说。后来随着工作的年头越来越久,有时候再次写联查,总是能想到这件事情,所以,今天总结一下:
1、Mysql查询是有缓存的,如果使用联查,一个表修改了,那么整个查询的缓存是不是就不存在了,但是如果是下面的查询好像还有缓存,这个是我开始尝试优化sql才考虑到的,那个时候已经离开了那家公司。
2、单个查询减少了锁竞争的情况,在同样的执行时间呢,等待时间可能会变短很多,这个是后续聊起锁竞争琢磨的。
3、就应用层来说,拆开的查询语句更容易实现扩展和高可用,这个是学习微服务那会思考的。
4、减少冗余,in代替关联,那么mysql会按照id顺序去检索,但是联查是随机关联,这个也是是开始尝试优化sql才考虑到的。
最后,必须强调,不要把前辈的话当作耳旁风,人家提醒你已经做的很到位了,千万不要不懂装懂,哪怕自己先试一试再去问,也好过我当初的做法,现在想想,嗨,程序员,不单单是思维编码,也要人情世故啊,也许主动一点,可以进步很快。
本文正在参加「技术专题19期 漫谈数据库技术」活动