MySQL性能优化四:多表查询优化
⼀、多表查询连接的选择:
相信这内连接,左连接什么的⼤家都⽐较熟悉了,当然还有左外连接什么的,基本⽤不上我就不贴出来了。这图只是让⼤家回忆⼀下,各种连接查询。 然后要告诉⼤家的是,需要根据查询的情况,想好使⽤哪种连接⽅式效率更⾼。
⼆、MySQL的JOIN实现原理
在MySQL 中,只有⼀种Join 算法,就是⼤名⿍⿍的Nested Loop Join,他没有其他很多数据库所提供的Hash Join,也没有Sort Merge Join。顾名思义,Nested Loop Join 实际上就是通过驱动表的结果集作为循环基础数据,然后⼀条⼀条的通过该结果集中的数据作为过滤条件到下⼀个表中查询数据,然后合并结果。如果还有第三个参与Join,则再通过前两个表的Join 结果集作为循环基础数据,再⼀次通过循环查询条件到第三个表中查询数据,如此往复。 ——摘⾃《MySQL 性能调优与架构设计》
三、补充:mysql对sql语句的容错问题
即在sql语句不完全符合书写建议的情况,mysql会允许这种情况,尽可能解释它:
1)⼀般cross join后⾯加上where条件,但是⽤cross join+on也是被解释为cross join+where;
mysql语句多表查询2)⼀般内连接都需要加上on限定条件,如上⾯场景⼀;如果不加会被解释为交叉连接;
3)如果连接表格使⽤的是逗号,会被解释为交叉连接;
注:sql标准中还有union join和natural inner join,mysql不⽀持,⽽且本⾝也没有多⼤意义,其实就是为了“健壮”。但是其实结果可以⽤上⾯的⼏种连接⽅式得到。
三、超⼤型数据尽可能尽⼒不要写⼦查询,使⽤连接(JOIN)去替换它:
当然,关于这句话,也不⼀定就全是这样。
1)因为在⼤型的数据处理中,⼦查询是⾮常常见的,特别是在查询出来的数据需要进⼀步处理的情况,⽆论是可读性还是效率上,这时候的⼦查都是更优。
oracle vm virtualbox文件怎么拷贝2)然⽽在⼀些特定的场景,可以直接从数据库读取就可以的,⽐如⼀个表(A表 a,b,c字段,需要内部数据交集)join⾃⼰的效率必然⽐放⼀个⼦查在where中快得多。
四、使⽤联合(UNION)来代替⼿动创建的临时表
UNION是会把结果排序的
union查询:它可以把需要使⽤临时表的两条或更多的select查询合并的⼀个查询中(即把两次或多次查询结果合并起来。)。在客户端的查询会话结束的时候,临时表会被⾃动删除,从⽽保证数据库整齐、⾼效。使⽤union来创建查询的时候,我们只需要⽤UNION作为关键字把多个select语句连接起来就可以了,要注意的是所有select语句中的字段数⽬要想同。
要求:两次查询的列数必须⼀致(列的类型可以不⼀样,但推荐查询的每⼀列,相对应的类型要⼀样)php音乐网站搭建
可以来⾃多张表的数据:多次sql语句取出的列名可以不⼀致,此时以第⼀个sql语句的列名为准。
如果不同的语句中取出的⾏,有完全相同(这⾥表⽰的是每个列的值都相同),那么union会将相同的⾏合并,最终只保留⼀⾏。也可以这样理解,union会去掉重复的⾏。
如果不想去掉重复的⾏,可以使⽤union all。
如果⼦句中有order by,limit,需⽤括号()包起来。推荐放到所有⼦句之后,即对最终合并的结果来排序或筛选。
注意:
1、UNION 结果集中的列名总是等于第⼀个 SELECT 语句中的列名
sql按字段排序
2、UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同
UNION ALL的作⽤和语法:007无暇赴死女特工
设计建议默认地,UNION 操作符选取不同的值。如果允许重复的值,请使⽤ UNION ALL。当 ALL 随 UNION ⼀起使⽤时(即 UNION ALL),不消除重复⾏。
五、总结
(1)对于要求全⾯的结果时,我们需要使⽤连接操作(LEFT JOIN / RIGHT JOIN / FULL JOIN);
(2)应尽量避免在 where ⼦句中对字段进⾏ null 值判断,否则将导致引擎放弃使⽤索引⽽进⾏全表扫描,如:
备注、描述、评论之类的可以设置为 NULL,其他最好不要使⽤NULL。
不要以为 NULL 不需要空间,⽐如:char(100) 型,在字段建⽴时,空间就固定了, 不管是否插⼊值(NULL也包含在内),都是占⽤100个字符的空间的,如果是varchar这样的变长字段, null 不占⽤空间。
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num = 0
(3)in 和 not in 也要慎⽤,否则会导致全表扫描,如:
对于连续的数值,能⽤ between 就不要⽤ in 了:
很多时候⽤ exists 代替 in 是⼀个好的选择:
(4)尽量使⽤数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连 接时会逐个⽐较字符串中每⼀个字符,⽽对于数字型⽽⾔只需要⽐较⼀次就够了。
(5)尽量使⽤表变量来代替临时表。如果表变量包含⼤量数据,请注意索引⾮常有限(只有主键索引)。
(6)不要以为使⽤MySQL的⼀些连接操作对查询有多么⼤的改善,其实核⼼是索引(别打我,下⼀篇讲)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。