1.多次join导致的慢sql
业务中有时会遇到使用多个join之后,虽然数据量不大,但是查询很慢的情况
问题原因:
从语义上来看,join能够帮助筛选数据,但是每一次关联,都可能产生冗余的值,所以就会因为笛卡尔积的缘故导致结果集越来越大。
解决思路:
把过滤条件放在前面,每一次join都尽量输出唯一值,减少冗余。
2.使用inner join使得mysql使用文件排序
问题原因
MySQL在遇到inner join联接语句时,使用的表关联算法是嵌套联接循环(Nest Loop Join)
,通过两层循环的手段进行依次的匹配操作,最后返回结果集合。嵌套连接循环的操作过程很像我们最简单的排序检索算法,两层循环结构。
进行连接的两个数据集合(数据表)分别被称为外侧表和内侧表,也称为驱动表和非驱动表。MySQL会将表中数据较小的表作为驱动表,另一张就是非驱动表:首先处理驱动表中每一条符合条件的数据,再将该数据和非驱动表进行连接匹配结束,直到循环结束后返回结果。
对于驱动表的字段,MySQL是可以直接排序的,而对于非驱动表的字段排序就需要通过循环查询的合并结果,也叫做临时表进行排序。数据库的底层是IO操作,数据库无法对表进行排序的话最后就会借助于磁盘,就会产生文件排序。
解决思路:
在查询中去掉inner join,使得sql能够对排序走索引。将去掉的inner join的语句在子查询中先查出来,也叫做派生表,然后再用派生表去做两张表的关联。子查询的结果存在内存中,在内存中就对他进行排序操作,所以就不会出现文件排序。
又由于派生表无法添加索引,所以要避免使用派生表,最好采用其他的方式来编写查询语句,大部分情况都比派生表来的快一些。可以考虑使用视图来取代派生表,查询时创建,查询完成之后删除视图