一次sql执行效率的讨论

http://www.itpub.net/406784.html

在测试机上测试了一把
发现和楼主测试的结构有些不同
表,索引,索引字段已经分析过.
我感觉区别在
1 NL探测Inner table的次数和这个结果记录数.
2 子查询效率,INDEX FAST FULL SCAN 代价.

[@more@]


[PHP]

SQL>
SQL> select count(*) from track;

COUNT(*)
----------
12337495

Elapsed: 00:00:00.01
SQL> select count(*) from terminal_user;

COUNT(*)
----------
305

Elapsed: 00:00:00.00
SQL>
SQL> set autotrace traceonly
SQL>
SQL>
SQL> select tu.* from terminal_user tu
2 where tu.tu_id not in (select distinct tu_id from track);

36 rows selected.

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 27 | 1944 | 614 (1)|
| 1 | NESTED LOOPS ANTI | | 27 | 1944 | 614 (1)|
| 2 | TABLE ACCESS FULL| TERMINAL_USER | 305 | 20740 | 3 (0)|
|* 3 | INDEX RANGE SCAN | TRACK_TUID_IDX | 11M| 42M| 2 (0)|
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("TU"."TU_ID"="TU_ID")

Note
-----
- 'PLAN_TABLE' is old version


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
627 consistent gets
0 physical reads
80 redo size
4224 bytes sent via SQL*Net to client
491 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
36 rows processed

由于terminal_user 仅有305条记录,
而且track表相关字段有索引,INDEX RANGE SCAN使得探测发挥了很高的效率.因此这个NL效率很高.
我们看到整个sql执行的Cost仅为614。


再来看 outer jion + null condition
SQL>
SQL> select tu.*
2 from terminal_user tu,
( select distinct tu_id from track ) tk
where tu.tu_id = tk.tu_id(+)
and tk.tu_id is null; 3 4 5

36 rows selected.

Elapsed: 00:00:03.15

Execution Plan
----------------------------------------------------------

----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 27 | 2187 | 10897 (16)|
|* 1 | HASH JOIN RIGHT ANTI | | 27 | 2187 | 10897 (16)|
| 2 | VIEW | | 278 | 3614 | 10894 (16)|
| 3 | HASH UNIQUE | | 278 | 1112 | 10894 (16)|
| 4 | INDEX FAST FULL SCAN| TRACK_TUID_IDX | 12M| 47M| 9365 (3)|
| 5 | TABLE ACCESS FULL | TERMINAL_USER | 305 | 20740 | 3 (0)|
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("TU"."TU_ID"="TK"."TU_ID")

Note
-----
- 'PLAN_TABLE' is old version


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
42111 consistent gets
0 physical reads
0 redo size
4224 bytes sent via SQL*Net to client
491 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
36 rows processed

我们可以看到 select distinct tu_id from track 的访问路径为 INDEX FAST FULL SCAN
而Cost就为9365.


SQL> select distinct tu_id from track;

278 rows selected.

Elapsed: 00:00:03.27

Execution Plan
----------------------------------------------------------

--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 278 | 1112 | 10894 (16)|
| 1 | HASH UNIQUE | | 278 | 1112 | 10894 (16)|
| 2 | INDEX FAST FULL SCAN| TRACK_BK_TUID_IDX | 12M| 47M| 9365 (3)|
--------------------------------------------------------------------------------

Note
-----
- 'PLAN_TABLE' is old version


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
42180 consistent gets
0 physical reads
124 redo size
5627 bytes sent via SQL*Net to client
667 bytes received via SQL*Net from client
20 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
278 rows processed

SQL> select /*+ INDEX(track,TRACK_BK_TUID_IDX)*/ distinct tu_id from track
2 ;

278 rows selected.

Elapsed: 00:00:03.69

Execution Plan
----------------------------------------------------------

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 278 | 1112 | 43705 (5)|
| 1 | SORT UNIQUE NOSORT| | 278 | 1112 | 43705 (5)|
| 2 | INDEX FULL SCAN | TRACK_BK_TUID_IDX | 12M| 47M| 42176 (1)|
-----------------------------------------------------------------------------

Note
-----
- 'PLAN_TABLE' is old version


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
41907 consistent gets
0 physical reads
132 redo size
5627 bytes sent via SQL*Net to client
667 bytes received via SQL*Net from client
20 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
278 rows processed

我发现select distinct tu_id from track无论是FFS还是IFS效率都不怎么样.


所以这里就产生一个问题.子查询的效率会受到数据量(影响到索引段的大小)的影响.
SQL> set autotrace off
SQL> analyze index TRACK_BK_TUID_IDX validate structure;

Index analyzed.

Elapsed: 00:00:15.65

SQL> select BLOCKS,USED_SPACE,DISTINCT_KEYS,LF_ROWS_LEN from index_stats;

BLOCKS USED_SPACE DISTINCT_KEYS LF_ROWS_LEN
---------- ---------- ------------- -----------
42752 198198860 278 197520787


[/PHP]

所以我感觉还是多做测试,用事实说话.

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/76065/viewspace-838204/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/76065/viewspace-838204/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值