• 【Oracle】单表先自行筛选后连接是SQL优化的必要步骤


    在微信公众号“我是程序汪”21年9月7日的文章“一张900w的数据表,16s执行的SQL优化到300ms”中,作者讲述了一种变常规查询到右连的优化方法,但他用的是MySQL数据库,今天我就来用本机的Oracle数据库来试试。

    前提:准备一个千万级大表,可以参考 https://www.cnblogs.com/heyang78/p/15239683.html 创建,下文中用到的是一千六百万大表。

    常规SQL:

    select * from emp_final a
    where a.name like 'AK%' and
    a.age between 30 and 50 and
    a.salary>20000 and a.salary<30000 and
    rownum<10;

    这句就是从符合筛选条件的记录里找出前十条。

    执行完耗时3.36秒,这个仅为实现需求未经雕琢的SQL比作者的MySQL数据库强四倍,Oracle受追捧不是没有原因的。

    优化后先筛选后直连的SQL:

    select a.* from emp_final a,(select id from emp_final where name like 'AK%' and age between 30 and 50 and salary>20000 and salary<30000 and rownum<10) b
    where a.id=b.id

    执行完耗时0.26秒,这个和作者优化后差不多,但我用的是一千六百万的表,接近作者九百万的表两倍了,再一次证明了Oracle的强大。

    两句SQL比较,大家就知道先筛选单表数据再做连接的好处了,就本例而言效率有十倍的提升。

    左联SQL:

    select b.* from (select id from emp_final where name like 'AK%' and age between 30 and 50 and salary>20000 and salary<30000 and rownum<10) a left join emp_final b
    on a.id=b.id

    执行完耗时0.35秒,这个稍长点。

    再换一种SQL:

    select * from emp_final where id in (select id from emp_final where name like 'AK%' and age between 30 and 50 and salary>20000 and salary<30000 and rownum<10)

    耗时0.31秒,这个就比左联强一点。

    其实直连、左联、半联结都是秒出,考虑到优化器和缓存,它们的性能在伯仲之间,不必厚彼薄此。

    SQL优化的核心思想就是及时抛却无用记录和无关列,此思想在本例得到了一定程度的体现。

    上文用到的执行结果(为简便有删减):

    SQL> select a.* from emp_final a,(select id from emp_final where name like 'AK%' and age between 30 and 50 and salary>20000 and salary<30000 and rownum<10) b
      2  where a.id=b.id;
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208001 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208002 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208003 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208004 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208005 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208006 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208007 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208008 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208009 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
    已选择9行。
    
    已用时间:  00: 00: 00.23
    SQL> select b.* from (select id from emp_final where name like 'AK%' and age between 30 and 50 and salary>20000 and salary<30000 and rownum<10) a left join emp_final b
      2  on a.id=b.id;
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208001 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208002 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208003 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208004 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208005 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208006 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208007 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208008 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208009 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
    已选择9行。
    
    已用时间:  00: 00: 00.21
    SQL> select * from emp_final where id in (select id from emp_final where name like 'AK%' and age between 30 and 50 and salary>20000 and salary<30000 and rownum<10);
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208004 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208007 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208009 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208002 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208003 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208001 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
            ID NAME                                            AGE     SALARY
    ---------- ---------------------------------------- ---------- ----------
    CREATE_TIME
    ---------------------------------------------------------------------------
       4208005 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208006 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
       4208008 AKUHVUGWHQ                                       41      29372
    07-9月 -21 06.32.42.000000 下午
    
    
    已选择9行。
    
    已用时间:  00: 00: 00.21
    SQL>

    --END--

  • 相关阅读:
    Disruptor-NET和内存栅栏
    SSDB:高性能数据库服务器
    PostgreSQL配置优化
    ADO.NET的弹性连接控制[ADO.NET idle connection resiliency]
    2013年度IT博客大赛跻身10强
    MongoDB 聚合管道(Aggregation Pipeline)
    验证码类库CaptchaMvc
    AngularJS SPA Template For Visual Studio
    .NET 4.0 版本号
    利用SSH Filesystem实现远程文件系统
  • 原文地址:https://www.cnblogs.com/heyang78/p/15239787.html
Copyright © 2020-2023  润新知