欢迎大家加入ORACLE超级群:17115662 免费解决各种ORACLE问题
本次测试来源于QQ群里聊天记录:关于sql走filter过滤的时候,子查询执行的次数。因为我们知道子查询执行的次数,决定了我们SQL的性能
1,数据库的版本
| SQL> select * from v$version;   BANNER —————————————————————- Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 – 64bi PL/SQL Release 10.2.0.4.0 – Production CORE    10.2.0.4.0      Production TNS for Linux: Version 10.2.0.4.0 – Production NLSRTL Version 10.2.0.4.0 – Production | 
2,创建测试表与索引
| SQL> create table scott.htz1 as select * from dba_objects;   Table created.   SQL> create table scott.htz2 as select * from dba_objects;   Table created.   SQL> create table scott.htz3 as select * from dba_objects;     Table created.   SQL>  SQL> create index scott.ind_htz3_object_owner on scott.htz3(object_id,owner);   Index created. | 
3,驱动表无重复值
| SQL> select *   2     from scott.htz1 a, scott.htz2 b   3    where a.object_id = b.object_id   4      and a.object_id in (select object_id   5                            from scott.htz3 c   6                           where c.owner = ‘SCOTT’   7                             and a.owner = ‘SYS’)   8   ;   no rows selected   SQL> @plan_by_last.sql SQL> set echo off Enter value for sqlid:  old   1: SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(nvl(‘&sqlid’,null),null,’ALLSTATS LAST’)) new   1: SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(nvl(”,null),null,’ALLSTATS LAST’))   PLAN_TABLE_OUTPUT —————————————————————————————- select *    from scott.htz1 a, scott.htz2 b   where a.object_id = b.object_id     and a.object_id in (select object_id                        from scott.htz3 c                          where c.owner = ‘SCOTT’                            and a.owner = ‘SYS’)   Plan hash value: 286543034   ———————————————————————————————————————————- | Id  | Operation           | Name                  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem | ———————————————————————————————————————————- |*  1 |  FILTER             |                       |      1 |        |      0 |00:00:00.96 |   47310 |       |       |          | |*  2 |   HASH JOIN         |                       |      1 |  38536 |  50068 |00:00:00.60 |    1386 |  7548K|  2031K| 8473K (0)| |   3 |    TABLE ACCESS FULL| HTZ1                  |      1 |  38535 |  50068 |00:00:00.05 |     693 |       |       |          | |   4 |    TABLE ACCESS FULL| HTZ2                  |      1 |  50965 |  50069 |00:00:00.10 |     693 |       |       |          | |*  5 |   FILTER            |                       |  50068 |        |      0 |00:00:00.23 |   45924 |       |       |          | |*  6 |    INDEX RANGE SCAN | IND_HTZ3_OBJECT_OWNER |  22962 |      1 |      0 |00:00:00.10 |   45924 |       |       |          | ———————————————————————————————————————————-   Predicate Information (identified by operation id): —————————————————      1 – filter( IS NOT NULL)    2 – access(“A”.”OBJECT_ID”=”B”.”OBJECT_ID”)    5 – filter(:B1=’SYS’)    6 – access(“OBJECT_ID”=:B1 AND “C”.”OWNER”=’SCOTT’)   Note —–    – dynamic sampling used for this statement   这里filter执行了50068次,而INDEX只执行了22962次,这里是因为有主表查询,把主表的过滤列推过来了 31 rows selected.   SQL>  SQL> select count(*)   2     from scott.htz1 a, scott.htz2 b   3    where a.object_id = b.object_id;     COUNT(*) ———-      50068 | 
4,有重复的值
| SQL> insert into scott.htz1 select * from scott.htz1;   50068 rows created.   SQL> commit;   Commit complete.     SQL> select count(*)   2     from scott.htz1 a, scott.htz2 b   3    where a.object_id = b.object_id;     COUNT(*) ———-     100136   这里看到两个表连接后还回了100316行记录 SQL> select count(distinct a.object_id) count_distinct   2     from scott.htz1 a, scott.htz2 b   3    where a.object_id = b.object_id;   COUNT_DISTINCT ————–          50068 这里看到表还回的不同值为50068个   SQL> @plan_by_last.sql SQL> set echo off Enter value for sqlid:  old   1: SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(nvl(‘&sqlid’,null),null,’ALLSTATS LAST’)) new   1: SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(nvl(”,null),null,’ALLSTATS LAST’))   PLAN_TABLE_OUTPUT ————————————————– SQL_ID  1gktx239rcv6f, child number 0 ————————————- select *    from scott.htz1 a, scott.htz2 b   where a.object_id = b.object_id     and a.object_id in (select object_id               from scott.htz3 c                          where c.owner = ‘SCOTT’                            and a.owner = ‘SYS’)   Plan hash value: 286543034   ——————————————————————————————————————————————- | Id  | Operation           | Name                  | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem | ——————————————————————————————————————————————- |*  1 |  FILTER             |                       |      1 |        |      0 |00:00:01.29 |   48000 |     68 |       |       |          | |*  2 |   HASH JOIN         |                       |      1 |  38536 |    100K|00:00:00.81 |    2076 |     68 |    13M|  2031K|   17M (0)| |   3 |    TABLE ACCESS FULL| HTZ1                  |      1 |  38535 |    100K|00:00:00.10 |    1383 |      0 |       |       |          | |   4 |    TABLE ACCESS FULL| HTZ2                  |      1 |  50965 |  50069 |00:00:00.10 |     693 |     68 |       |       |          | |*  5 |   FILTER            |                       |  50068 |        |      0 |00:00:00.24 |   45924 |      0 |       |       |          | |*  6 |    INDEX RANGE SCAN | IND_HTZ3_OBJECT_OWNER |  22962 |      1 |      0 |00:00:00.10 |   45924 |      0 |       |       |          | ——————————————————————————————————————————————-   Predicate Information (identified by operation id): —————————————————      1 – filter( IS NOT NULL)    2 – access(“A”.”OBJECT_ID”=”B”.”OBJECT_ID”)    5 – filter(:B1=’SYS’)    6 – access(“OBJECT_ID”=:B1 AND “C”.”OWNER”=’SCOTT’)   Note —–    – dynamic sampling used for this statement   通过执行计划,我们可以看到FILTER这里仍然50068,说明是DISCOUNT的值的总行数,而不是主表还回的行数 30 rows selected.   | 
5,连接列包括多个空值的情况
| SQL> update scott.htz1 set object_id=” where rownum<10000;   9999 rows updated.   SQL> commit;   Commit complete.     SQL> update scott.htz2 set object_id=” where rownum<10000;   9999 rows updated.   SQL> commit;   Commit complete.       SQL> select count(distinct a.object_id) count_distinct   2     from scott.htz1 a, scott.htz2 b   3    where a.object_id = b.object_id;   COUNT_DISTINCT ————–          40069           连接列还回的DISCOUNT的值           SQL> select *   2     from scott.htz1 a, scott.htz2 b   3    where a.object_id = b.object_id   4      and a.object_id in (select object_id   5                            from scott.htz3 c   6                           where c.owner = ‘SCOTT’   7                             and a.owner = ‘SYS’)   8   ;   no rows selected   SQL> @plan_by_last.sql SQL> set echo off Enter value for sqlid:  old   1: SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(nvl(‘&sqlid’,null),null,’ALLSTATS LAST’)) new   1: SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(nvl(”,null),null,’ALLSTATS LAST’))   PLAN_TABLE_OUTPUT ——————————————————————————————————————————————————————————————————– SQL_ID  1gktx239rcv6f, child number 0 ————————————- select *    from scott.htz1 a, scott.htz2 b   where a.object_id = b.object_id     and a.object_id in (select object_id               from scott.htz3 c                          where c.owner = ‘SCOTT’                            and a.owner = ‘SYS’)   Plan hash value: 286543034   ——————————————————————————————————————————————- | Id  | Operation           | Name                  | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem | ——————————————————————————————————————————————- |*  1 |  FILTER             |                       |      1 |        |      0 |00:00:01.15 |   34646 |     19 |       |       |          | |*  2 |   HASH JOIN         |                       |      1 |  38536 |  80138 |00:00:00.86 |    2076 |     19 |    12M|  2029K|   15M (0)| |   3 |    TABLE ACCESS FULL| HTZ1                  |      1 |  38535 |    100K|00:00:00.10 |    1383 |     19 |       |       |          | |   4 |    TABLE ACCESS FULL| HTZ2                  |      1 |  50965 |  50069 |00:00:00.09 |     693 |      0 |       |       |          | |*  5 |   FILTER            |                       |  40069 |        |      0 |00:00:00.18 |   32570 |      0 |       |       |          | |*  6 |    INDEX RANGE SCAN | IND_HTZ3_OBJECT_OWNER |  16285 |      1 |      0 |00:00:00.07 |   32570 |      0 |       |       |          | ——————————————————————————————————————————————-   Predicate Information (identified by operation id): —————————————————      1 – filter( IS NOT NULL)    2 – access(“A”.”OBJECT_ID”=”B”.”OBJECT_ID”)    5 – filter(:B1=’SYS’)    6 – access(“OBJECT_ID”=:B1 AND “C”.”OWNER”=’SCOTT’)   Note —–    – dynamic sampling used for this statement     30 rows selected. | 
5,总结
通过上面的测试,我们可以看到FILTER过滤的时候,子查询执行的次数为count(DISCOUNT  主键连接列)


报歉!评论已关闭。