优化select count(*) (转oracle培训老师的文章)
2011-08-02 13:54
501 查看
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 | P->S | QC(RAND) |
| 4 | SORT AGGREGATE | | 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,优化无止境呀!
只有你把握原理,一切尽在掌握!
from:/article/10554296.html
这句话比较简单,但很有玄机!对这句话运行的理解,反映了你对数据库的理解深度!
建立实验的大表他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 | P->S | QC(RAND) |
| 4 | SORT AGGREGATE | | 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,优化无止境呀!
只有你把握原理,一切尽在掌握!
from:/article/10554296.html
相关文章推荐
- oracle select count一次优化经历
- Oracle性能优化之资源管理_超越OCP精通Oracle视频教程培训36
- Oracle 11g通过提高IO吞吐量(修改_db_file_optimizer_read_count)来优化全表扫描
- ORACLE SQL性能优化(内部培训资料)
- 关于HIVE的SELECT count(*) 优化
- oracle count()查询速度优化
- Oracle优化经典文章------索引原理篇
- SQL Select count(*)和Count(1)的区别和执行方式及SQL性能优化
- Oracle SQL优化文章不必再看
- SQL优化:一篇文章说清楚Oracle Hint的正确使用姿势
- Oracle优化经典文章------磁盘I/O和碎片篇
- Oracle优化经典文章------索引原理篇
- Oracle培训方案(中文版)_Database 10g 性能优化
- MySQL 的 select count() 优化
- Oracle优化经典文章------索引原理篇
- [Oracle] “表中有数据,但select count(*)的结果为0”问题的解决办法
- Oracle性能优化之COUNT
- Oracle优化经典文章------索引原理篇
- Mysql 优化之 select count 效率
- 小布老师Oracle培训视频