Oracle 分区表收集分区统计信息、索引信息

--删除表
DROP TABLE TEST3;

--1.创建按日分区测试表
CREATE TABLE TEST3(ID INT, PARDATE DATE)
PARTITION BY RANGE (PARDATE) INTERVAL (NUMTODSINTERVAL (1,'DAY'))
(
  PARTITION P_20180101 VALUES LESS THAN (TO_DATE('2018-01-02', 'YYYY-MM-DD'))
);
表已创建。

--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');

--查看分区统计信息
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';
 
PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22

--查看全局统计信息
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- ---------------
       200 03-SEP-22 
 
--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;

--查看分区统计信息
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';

PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22
SYS_P905
SYS_P906
SYS_P907

6 rows selected.

--查看全局统计信息
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- ---------------
       200 03-SEP-22 

--3.仅收集新增partition的统计信息
-----exec DBMS_STATS.GATHER_TABLE_STATS(ownname => 'AML',tabname => 'T2A_TRANS',partname => 'PT_20220214',granularity => 'PARTITION',estimate_percent => 0.001,degree =>10);
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P905',granularity => 'PARTITION');
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P906',granularity => 'PARTITION');
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P907',granularity => 'PARTITION');

--4.查看分区的统计信息
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';
 
PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22
SYS_P905                              100 03-SEP-22
SYS_P906                              100 03-SEP-22
SYS_P907                              100 03-SEP-22

6 rows selected.

--5.查看全局的统计信息, 发现全局统计信息仍陈旧(200条)
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';
 
  NUM_ROWS LAST_ANALYZED
---------- ---------------
       200 02-SEP-22
 
--6.查看oracle预估返回行数是否正确,单分区准确,跨分区就不准确
set autotrace traceonly
SELECT COUNT(*)
  FROM TEST3
 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 |
-------------------------------------------------------------------------------------------------
SELECT COUNT(*)
  FROM TEST3
 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 |
-------------------------------------------------------------------------------------------------

--跨分区统计信息就不准确
SELECT COUNT(*)
  FROM TEST3
 WHERE PARDATE IN
       (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 ;

--查看分区统计信息
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';

PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22
SYS_P905                              100 03-SEP-22
SYS_P906                              100 03-SEP-22
SYS_P907                              100 03-SEP-22
SYS_P908
SYS_P909

8 rows selected.

--查看全局统计信息
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- ---------------
       200 03-SEP-22 

--8.采用AUTO收集,仅收集增加的一个分区统计信息,另外一个不收集
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P908',granularity => 'AUTO');
 
--9.查看分区的统计信息(SYS_P265为空)
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';
 
PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22
SYS_P905                              100 03-SEP-22
SYS_P906                              100 03-SEP-22
SYS_P907                              100 03-SEP-22
SYS_P908                              100 03-SEP-22
SYS_P909

8 rows selected.

--查看全局统计信息
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- ---------------
       700 03-SEP-22


--10.查看全局统计信息,发现条数为700条。意味着全局统计信息不仅仅是将新收集分区的统计信息直接加到全局上去,而是重新全部收集了。
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';
 
  NUM_ROWS LAST_ANALYZED
---------- ---------------
       700 03-SEP-22

--收集掉另外一个分区再继续测试
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P909',granularity => 'AUTO');

--查看分区统计信息
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';

PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22
SYS_P905                              100 03-SEP-22
SYS_P906                              100 03-SEP-22
SYS_P907                              100 03-SEP-22
SYS_P908                              100 03-SEP-22
SYS_P909                              100 03-SEP-22

8 rows selected.

--查看全局统计信息
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- ---------------
       700 03-SEP-22

--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 ;

--查看分区统计信息
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';

PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22
SYS_P905                              100 03-SEP-22
SYS_P906                              100 03-SEP-22
SYS_P907                              100 03-SEP-22
SYS_P908                              100 03-SEP-22
SYS_P909                              100 03-SEP-22
SYS_P910
SYS_P911

10 rows selected.

--查看全局统计信息
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';

 NUM_ROWS LAST_ANALYZED
---------- ---------------
       700 03-SEP-22

--11.通过测试可以通过指定granularity => 'APPROX_GLOBAL AND PARTITION',机制是仅将指定分区的统计信息增加到全局信息中。
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P910',granularity => 'APPROX_GLOBAL AND PARTITION');

--可以看到本次全局统计信息仅将SYS_P890的100条增加到全局统计信息中,而不是全部收集
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';

PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22
SYS_P905                              100 03-SEP-22
SYS_P906                              100 03-SEP-22
SYS_P907                              100 03-SEP-22
SYS_P908                              100 03-SEP-22
SYS_P909                              100 03-SEP-22
SYS_P910                              100 03-SEP-22
SYS_P911

10 rows selected.

SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';

  NUM_ROWS LAST_ANALYZED
---------- ---------------
       800 03-SEP-22

--使用granularity => 'APPROX_GLOBAL AND PARTITION' 收集另外一个分区的统计信息	   
exec dbms_stats.gather_table_stats(user,'TEST3',partname => 'SYS_P911',granularity => 'APPROX_GLOBAL AND PARTITION');

--查看分区统计信息
set linesize 200
col PARTITION_NAME for a30
SELECT P.PARTITION_NAME, P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TAB_PARTITIONS P
 WHERE TABLE_NAME = 'TEST3';
 
PARTITION_NAME                   NUM_ROWS LAST_ANALYZED
------------------------------ ---------- ---------------
P_20180101                              0 03-SEP-22
SYS_P903                              100 03-SEP-22
SYS_P904                              100 03-SEP-22
SYS_P905                              100 03-SEP-22
SYS_P906                              100 03-SEP-22
SYS_P907                              100 03-SEP-22
SYS_P908                              100 03-SEP-22
SYS_P909                              100 03-SEP-22
SYS_P910                              100 03-SEP-22
SYS_P911                              100 03-SEP-22

10 rows selected.

--查看全局统计信息
SELECT P.NUM_ROWS, P.LAST_ANALYZED
  FROM DBA_TABLES P
 WHERE TABLE_NAME = 'TEST3';
 
  NUM_ROWS LAST_ANALYZED
---------- ---------------
       900 03-SEP-22

--12.再测试下跨分区的准确性,答案是准确的
SET AUTOTRACE TRACEONLY
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) |
------------------------------------------------------------------------------------------------

你可能感兴趣的:(Oracle,分区表,oracle,数据库)