Oracle 收集分区统计信息

--删除表
DROP TABLE TEST3;
--1.创建按日分区测试表
SQL> CREATE TABLE TEST3(ID INT, PARDATE DATE)
  2  PARTITION BY RANGE (PARDATE) INTERVAL (NUMTODSINTERVAL (1,'DAY'))
  3  (
  4    PARTITION P_20180101 VALUES LESS THAN (TO_DATE('2018-01-02', 'YYYY-MM-DD'))
  5  );
表已创建。
--2.插入2天的数据,每天100条数据
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210324','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210325','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
COMMIT;
--3.模拟生产,先收集下全局统计信息,避免动态采集
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'TEST3');
--4.继续插入3天的数据,每天100条数据
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210326','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210327','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210328','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
COMMIT;
--3.仅收集新增partition的统计信息
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P261',granularity => 'PARTITION');
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P262',granularity => 'PARTITION');
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P263',granularity => 'PARTITION');
--4.查看分区的统计信息
SQL> set linesize 200
SQL> SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  2    FROM DBA_TAB_PARTITIONS P
  3   WHERE TABLE_NAME = 'TEST3';

PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- --------------
P_20180101                              0 26-3-21
SYS_P259                              100 26-3-21
SYS_P260                              100 26-3-21
SYS_P261                              100 26-3-21
SYS_P262                              100 26-3-21
SYS_P263                              100 26-3-21
--5.查看全局的统计信息, 发现全局统计信息仍陈旧(200条)
SQL> SELECT P.NUM_ROWS, P.LAST_ANALYZED
  2    FROM DBA_TABLES P
  3   WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- --------------
       200 26-3-21

--6.查看oracle预估返回行数是否正确,单分区准确,跨分区就不准确
SQL> set autotrace traceonly
SQL> SELECT COUNT(*)
  2    FROM TEST3
  3   WHERE PARDATE = TO_DATE('20210326', 'YYYYMMDD');
-------------------------------------------------------------------------------------------------
| Id  | Operation               | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |       |     1 |     8 |     3   (0)| 00:00:01 |       |       |
|   1 |  SORT AGGREGATE         |       |     1 |     8 |            |          |       |       |
|   2 |   PARTITION RANGE SINGLE|       |   100 |   800 |     3   (0)| 00:00:01 |  1181 |  1181 |
|*  3 |    TABLE ACCESS FULL    | TEST3 |   100 |   800 |     3   (0)| 00:00:01 |  1181 |  1181 |
-------------------------------------------------------------------------------------------------
SQL> SELECT COUNT(*)
  2    FROM TEST3
  3   WHERE PARDATE = TO_DATE('20210327', 'YYYYMMDD');
-------------------------------------------------------------------------------------------------
| Id  | Operation               | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |       |     1 |     8 |     3   (0)| 00:00:01 |       |       |
|   1 |  SORT AGGREGATE         |       |     1 |     8 |            |          |       |       |
|   2 |   PARTITION RANGE SINGLE|       |   100 |   800 |     3   (0)| 00:00:01 |  1182 |  1182 |
|*  3 |    TABLE ACCESS FULL    | TEST3 |   100 |   800 |     3   (0)| 00:00:01 |  1182 |  1182 |
-------------------------------------------------------------------------------------------------
--跨分区统计信息就不准确
SQL> SELECT COUNT(*)
  2    FROM TEST3
  3   WHERE PARDATE IN
  4         (TO_DATE('20210326', 'YYYYMMDD'), TO_DATE('20210327', 'YYYYMMDD'));
-------------------------------------------------------------------------------------------------
| Id  | Operation               | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |       |     1 |     8 |     4   (0)| 00:00:01 |       |       |
|   1 |  SORT AGGREGATE         |       |     1 |     8 |            |          |       |       |
|   2 |   PARTITION RANGE INLIST|       |     1 |     8 |     4   (0)| 00:00:01 |KEY(I) |KEY(I) |
|*  3 |    TABLE ACCESS FULL    | TEST3 |     1 |     8 |     4   (0)| 00:00:01 |KEY(I) |KEY(I) |
-------------------------------------------------------------------------------------------------

--7.新插入两个分区数据,
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210329','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210330','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
COMMIT
--8.采用AUTO收集,仅收集增加的一个分区统计信息,另外一个不收集
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P264',granularity => 'AUTO');

--9.查看分区的统计信息(SYS_P265为空)
SQL> SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  2   FROM DBA_TAB_PARTITIONS P
  3  WHERE TABLE_NAME = 'TEST3';

PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- --------------
P_20180101                              0 26-3-21
SYS_P259                              100 26-3-21
SYS_P260                              100 26-3-21
SYS_P261                              100 26-3-21
SYS_P262                              100 26-3-21
SYS_P263                              100 26-3-21
SYS_P264                              100 26-3-21
SYS_P265
--10.查看全局统计信息,发现条数为700条。意味着全局统计信息不仅仅是将新收集分区的统计
--信息直接加到全局上去,而是重新全部收集了。
SQL> SELECT P.NUM_ROWS, P.LAST_ANALYZED
  2    FROM DBA_TABLES P
  3   WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- --------------
       700 26-3-21
--收集掉另外一个分区再继续测试
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P265',granularity => 'AUTO');

--11.再插入两个分区数据
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210331','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
INSERT INTO TEST3
SELECT ROWNUM,TO_DATE('20210401','YYYYMMDD') FROM DBA_OBJECTS WHERE ROWNUM <= 100;
COMMIT
       
--11.通过测试可以通过指定granularity => 'APPROX_GLOBAL AND PARTITION',机制是
--仅将指定分区的统计信息增加到全局信息中。
SQL> exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P266',granularity => 'APPROX_GLOBAL AND PARTITION');
--可以看到本次全局统计信息仅将SYS_P266的100条增加到全局统计信息中,而不是全部收集
SQL> SELECT P.NUM_ROWS, P.LAST_ANALYZED
  2    FROM DBA_TABLES P
  3   WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- --------------
       800 26-3-21
SQL> exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P267',granularity => 'APPROX_GLOBAL AND PARTITION');
--查看分区统计信息
SQL> SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  2   FROM DBA_TAB_PARTITIONS P
  3  WHERE TABLE_NAME = 'TEST3';

PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- --------------
P_20180101                              0 26-3-21
SYS_P259                              100 26-3-21
SYS_P260                              100 26-3-21
SYS_P261                              100 26-3-21
SYS_P262                              100 26-3-21
SYS_P263                              100 26-3-21
SYS_P264                              100 26-3-21
SYS_P265                              100 26-3-21
SYS_P266                              100 26-3-21
SYS_P267                              100 26-3-21
--查看全局统计信息
SQL> SELECT P.NUM_ROWS, P.LAST_ANALYZED
  2    FROM DBA_TABLES P
  3   WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- --------------
       900 26-3-21
--12.再测试下跨分区的准确性,答案是准确的
SQL> SET AUTOTRACE TRACEONLY
SQL> SELECT * FROM TEST3 WHERE PARDATE = TO_DATE('20210331', 'YYYYMMDD');
----------------------------------------------------------------------------
| Id  | Operation              | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |       |   100 |  1100 |     3   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE SINGLE|       |   100 |  1100 |     3   (0)| 00:00:01 |  1186 |  1186 |
|*  2 |   TABLE ACCESS FULL    | TEST3 |   100 |  1100 |     3   (0)| 00:00:01 |  1186 |  1186 |
------------------------------------------------------------------------------------------------

SQL> SELECT * FROM TEST3 WHERE PARDATE = TO_DATE('20210401', 'YYYYMMDD');
------------------------------------------------------------------------------------------------
| Id  | Operation              | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |       |   100 |  1100 |     3   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE SINGLE|       |   100 |  1100 |     3   (0)| 00:00:01 |  1187 |  1187 |
|*  2 |   TABLE ACCESS FULL    | TEST3 |   100 |  1100 |     3   (0)| 00:00:01 |  1187 |  1187 |
------------------------------------------------------------------------------------------------


SQL> SELECT * FROM TEST3 WHERE PARDATE IN (TO_DATE('20210331', 'YYYYMMDD'),TO_DATE('20210401', 'YYYYMMDD'));
------------------------------------------------------------------------------------------------
| Id  | Operation              | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |       |   200 |  2200 |     4   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE INLIST|       |   200 |  2200 |     4   (0)| 00:00:01 |KEY(I) |KEY(I) |
|*  2 |   TABLE ACCESS FULL    | TEST3 |   200 |  2200 |     4   (0)| 00:00:01 |KEY(I) |KEY(I) |
------------------------------------------------------------------------------------------------

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值