加入收藏 | 设为首页 | 会员中心 | 我要投稿 聊城站长网 (https://www.0635zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MySQL中的反连接有啥用

发布时间:2022-01-10 16:11:25 所属栏目:MySql教程 来源:互联网
导读:这篇文章给大家分享的是有关MySQL中的反连接有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 在表的连接上,半连接,反连接本身很平常,但是统计信息的不够丰富导致执行计划的评估中可能会出现较大差别,会很可能把
       这篇文章给大家分享的是有关MySQL中的反连接有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
 
        在表的连接上,半连接,反连接本身很平常,但是统计信息的不够丰富导致执行计划的评估中可能会出现较大差别,会很可能把半连接,反连接的实现方式和执行路径的差异放大,导致SQL性能变差,同时MySQL里面in和exists的差距也在减小。
 
       里面的列select_type PRIMARY代表子查询中的最外层查询,此处不是主键查询。而SUBQUERY代表是子查询内层查询的第一个SELECT,结果不会依赖于外部查询的结果集。
 
从type为ALL代表是全表扫描,所以这样一个查询两个表都是全表扫描,在MySQL内部解析的时候是怎么分解的呢。我们通过explain extended的方式来得到更详细的信息。
 
/* select#1 */
select test . t_fund_info . account AS account
  from test . t_fund_info
 where ((test . t_fund_info . money >= 300) and
       (not (< in_optimizer >
         (test . t_fund_info . account, test . t_fund_info .
          account in
          (< materialize >
           ( /* select#2 */
                 select test . t_user_login_record . account
                   from test . t_user_login_record
                  where (test . t_user_login_record . add_time >= '2016-06-01')), <
           primary_index_lookup >
           (test . t_fund_info . account in < temporary
            table > on < auto_key >
            where((test . t_fund_info . account = materialized - subquery .
                        account))))))))可以看到启用了临时表,查取了子查询的数据作为后续的缓存处理数据.
 
  这样的处理,究竟对性能提升有多大呢,其实不大,而且性能改进也很有限。
 
 我们换一个思路,那就是使用not exists
 
explain extended select t1.account from t_fund_info t1 where t1.money >=300 and  not exists (select distinct(t2.account) from t_user_login_record t2 where t1.account=t2.account and t2.add_time >='2016-06-01');这种方式在MySQL是如何分解的呢。
 
select test . t1 . account AS account
  from test . t_fund_info t1
 where ((test . t1 . money >= 300) and
       (not
        (exists ( /* select#2 */
                   select test . t2 . account
                     from test . t_user_login_record t2
                    where ((test . t1 . account = test . t2 . account) and
                          (test . t2 . add_time >= '2016-06-01'))))))  可以看到几乎没有做什么特别的改动。
 
这一点在5.5,5.6,5.7中都是很相似的处理思路。
 
  当然这种方式相对来说性能提升都不大。一个局限就在于统计信息不够丰富,所以自动评估就会出现很大的差距。
 
  这个地方我们稍放一放,我们添加一个索引之后再来看看。
 
create index ind_account_id2 on t_user_login_record(account);
然后使用not in的方式查看解析的详情。
 
select test . t_fund_info . account AS account
  from test . t_fund_info
 where ((test . t_fund_info . money >= 300) and
       (not (< in_optimizer >
         (test . t_fund_info .
          account, < exists >
          (< index_lookup >
           (< cache > (test . t_fund_info . account) in t_user_login_record on
            ind_account_id2
            where((test . t_user_login_record . add_time >= '2016-06-01') and
                       (< cache > (test . t_fund_info . account) = test .
                        t_user_login_record . account))))))))
 
可以看到这个方式有了索引,not in和not exits的解析方式很相似。有一个差别就是在子查询外有了<cache>的处理方式。

(编辑:聊城站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!