微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

oracle优化之count的优化-避免全表扫描

select count(*) from t1;
这句话比较简单,但很有玄机!对这句话运行的理解,反映了你对数据库的理解深度!
建立实验的大表他t1
sql> conn scott/tiger
已连接。
sql> drop table t1 purge;
表已删除
sql> create table t1 as select * from emp where 0=9;
表已创建。
sql> insert into t1 select * from emp;
已创建14行。
sql> insert into t1 select * from t1;
已创建14行。
sql> /
已创建28行。
sql> /
已创建56行。
sql> /
已创建112行。
sql> /
已创建224行。
sql> /
已创建448行。
sql> /
已创建896行。
sql> /
已创建1792行。
sql> /
已创建3584行。
sql> /
已创建7168行。
sql> /
已创建14336行。
sql> /
已创建28672行。
sql> /
已创建57344行。
sql> commit;
提交完成。
收集统计信息
sql> execute dbms_stats.gather_table_stats('SCott','T1');
PL/sql 过程已成功完成。
sql> SET AUTOT TRACE EXP
sql> SELECT COUNT(*) FROM T1;
执行计划
--------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 124 (4)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T1 | 116K| 124 (4)| 00:00:02 |
-----------------------------------------------------
代价为124,运行的计划为全表扫描。
sql> DELETE T1 WHERE DEPTNO=10;
删除24576行。
sql> COMMIT;
提交完成。
sql> execute dbms_stats.gather_table_stats('SCott','T1');
PL/sql 过程已成功完成。
sql> SELECT COUNT(*) FROM T1;
执行计划
-----------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 123 (3)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T1 | 90286 | 123 (3)| 00:00:02 |
-----------------------------------------------------
sql> --1.降低高水位
sql> alter table t1 move tablespace users;
表已更改。
sql> execute dbms_stats.gather_table_stats('SCott','T1');
PL/sql 过程已成功完成。
sql> SELECT COUNT(*) FROM T1;
执行计划
-----------------------------------------------------
| Id | Operation | Name | Rows |Cost (%cpu)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 102 (3)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T1 | 90667 | 102 (3)| 00:00:02 |
-----------------------------------------------------
代价为102,降低了
sql> --2.修改pctfree
sql> alter table t1 pctfree 0;
表已更改。
sql> alter table t1 move tablespace users;
表已更改。
sql> execute dbms_stats.gather_table_stats('SCott','T1');
PL/sql 过程已成功完成。
sql> SELECT COUNT(*) FROM T1;
执行计划
----------------------------------------------------------
Plan hash value: 3724264953

-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 92 (4)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T1 | 91791 | 92 (4)| 00:00:02 |
-------------------------------------------------------------------
代价为92,降低了10%
sql> --3.参数db_file_multiblock_read_count=64
sql> --4.建立b*tree类型的索引
sql> create index i1 on t1(empno);
索引已创建。
sql> execute dbms_stats.gather_index_stats('SCott','I1');
PL/sql 过程已成功完成。
sql> SELECT COUNT(*) FROM T1;
执行计划
----------------------------------------------------------
Plan hash value: 3724264953

-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 92 (4)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T1 | 91791 | 92 (4)| 00:00:02 |
-------------------------------------------------------------------
为什么没有使用我们建立的索引,因为null不进入普通的索引!
sql> alter table t1 modify(empno not null);
表已更改。
sql> SELECT COUNT(*) FROM T1;
执行计划
----------------------------------------------------------
Plan hash value: 129980005

----------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time |
----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 36 (6)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FAST FULL SCAN| I1 | 91791 | 36 (6)| 00:00:01 |
----------------------------------------------------------------------
我们的索引起到了很大的作用!
sql> --5.使用并行查询的特性

强制全表扫描,屏蔽索引
sql> select /*+ full(t1) parallel(t1 2) */ COUNT(*) FROM T1;
执行计划
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time | TQ |IN-OUT| PQ distrib |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 51 (4)| 00:00:01 | | | |
| 1 | SORT AGGREGATE | | 1 | | | | | |
| 2 | PX COORDINATOR | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10000 | 1 | | | Q1,00 | P->S | QC(RAND) |
| 4 | SORT AGGREGATE | | 1 | | | Q1,00 | Pcwp | |
| 5 | PX BLOCK IteraTOR | | 91791 | 51 (4)| 00:00:01 | Q1,00 | PCWC| |
| 6 | TABLE ACCESS FULL| T1 | 91791 | 51 (4)| 00:00:01 | Q1,00 | Pcwp | |
-----------------------------------------------------------------------------------------------
并行度越高,代价越低
sql> alter table t1 parallel 4;
表已更改。
也可以通过使用表的属性来定义并行度,但是影响比较大,不如语句级别限制并行!
sql> select count(*) from t1;
执行计划
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time | TQ |IN-OUT| PQdistrib |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 25 (0)| 00:00:01 | | | |
| 1 | SORT AGGREGATE | | 1 | | | | | |
| 2 | PX COORDINATOR | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10000 | 1 | | | Q1,00 | Pcwp | |
| 5 | PX BLOCK IteraTOR | | 91791 | 25 (0)| 00:00:01 | Q1,00 | PCWC | |
| 6 | TABLE ACCESS FULL| T1 | 91791 | 25 (0)| 00:00:01 | Q1,00 | Pcwp | |
---------------------------------------------------------------------------------------------
代价为25,代价比两个的又少一半!
sql> --6.建立位图索引来避免全表扫描
sql> create bitmap index i2 on t1(deptno);
索引已创建。
sql> execute dbms_stats.gather_index_stats('SCott','I2');
PL/sql 过程已成功完成。
sql> select count(*) from t1;
执行计划
----------------------------------------------------------
Plan hash value: 3738977131

------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | BITMAP CONVERSION COUNT | | 91791 | 4 (0)| 00:00:01 |
| 3 | BITMAP INDEX FAST FULL SCAN| I2 | | | |
------------------------------------------------------------------------------
sql> alter index i2 parallel 4;
索引已更改。
sql> select count(*) from t1;
执行计划
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%cpu)| Time | TQ |IN-OUT| PQ distrib |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 | | | |
| 1 | SORT AGGREGATE | | 1 | | | | | |
| 2 | PX COORDINATOR | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10000 | 1 | | | Q1,00 | P->S | QC (RAND) |
| 4 | SORT AGGREGATE | | 1 | | | Q1,00 | Pcwp | |
| 5 | PX BLOCK IteraTOR | | 91791 | 2 (0)| 00:00:01 | Q1,00 |PCWC | |
| 6 | BITMAP CONVERSION COUNT | | 91791 | 2 (0)| 00:00:01 | Q1,00 |Pcwp | |
| 7 | BITMAP INDEX FAST FULL SCAN| I2 | | | | Q1,00 | Pcwp | |
--------------------------------------------------------------------------------------------
代价为2,原来为124,优化无止境呀!
只有你把握原理,一切尽在掌握!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐