-- 1. 통계정보 담는 테이블 생성
EXEC DBMS_STATS.CREATE_STAT_TABLE('OWNER', 'STAT_BACKUP_XSOFT', 'SYSTEM');
-- 2. 통계정보 export 스크립트
exec dbms_stats.export_table_stats(ownname=>'OWNER',tabname=>'XSOFT_T',statid=>'XSOFT_T',statown=>'OWNER',stattab=>'STAT_BACKUP_XSOFT',cascade=>true);
-- 3. 통계정보 파일 export
exp userid=id/password file=stat_backup_xsoft.dmp tables=stat_backup_xsoft
-- 4. 통계정보 파일 import
imp userid=id/password file=stat_backup_xsoft.dmp tables=stat_backup_xsoft
-- 5. 통계정보 import 스크립트
EXEC DBMS_STATS.IMPORT_TABLE_STATS(OWNNAME=>'OWNER',TABNAME=>'XSOFT_T',STATID=>'XSOFT_T',CASCADE=>TRUE,STATOWN=>'OWNER',STATTAB=>'STAT_BACKUP_XSOFT');
-- 6. 통계정보 담는 테이블 삭제
DROP TABLE KIC.STAT_BACKUP_XSOFT;
1) 'Pending Statistics'가 생성되도록 'Attribute' 변경
2) 통계정보 수집하여 'Pending Statistics'로 저장
3) 'Pending Statistics'로 저장된 통계정보를 이용한 SQL Plan 검증
4) 'Pending Statistics'를 Publish하여 'Publish Statistics'로 대체
-- 1. 오라클 버전 확인
SELECT *
FROM v$version;
BANNER
----------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
-- 2. GET_PREFS 값 확인
SELECT DBMS_STATS.GET_PREFS('PUBLISH') PUBLISH
FROM DUAL;
PUBLISH
--------
TRUE
-- TRUE : 통계정보가 수집되자마자 바로 Publish
-- FALSE : 수집된 통계정보는 Publish 되지 않고 Pending
DBMS_STATS.GET_PREFS (pname IN VARCHAR2,
ownname IN VARCHAR2 DEFAULT NULL,
tabname IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2;
parameter | values | description |
---|---|---|
pname | CASCADE | he value determines whether or not index statistics are collected as part of gathering table statistics. |
DEGREE | The value determines degree of parallelism used for gathering statistics. | |
ESTIMATE_PERCENT | The value determines the percentage of rows to estimate. The valid range is '0.000001,100'. Use the constant DBMS_STATS.AUTO_SAMPLE_SIZE to have Oracle determine the appropriate sample size for good statistics. This is the default. | |
METHOD_OPT | The value controls column statistics collection and histogram creation. It accepts either of the following options, or both in combination: *. FOR ALL 'INDEXED / HIDDEN' COLUMNS 'size_clause' *. FOR COLUMNS 'size clause' column/attribute 'size_clause' ',column/attribute 'size_clause'...' size_clause is defined as size_clause := SIZE 'integer / REPEAT / AUTO / SKEWONLY' column is defined as column := column_name / (extension) | |
NO_INVALIDATE | he value controls the invalidation of dependent cursors of the tables for which statistics are being gathered. Does not invalidate the dependent cursors if set to TRUE. The procedure invalidates the dependent cursors immediately if set to FALSE. Use DBMS_STATS.AUTO_INVALIDATE to have Oracle decide when to invalidate dependent cursors. This is the default. | |
GRANULARITY | The value determines granularity of statistics to collect (only pertinent if the table is partitioned). *. 'ALL' - gathers all (subpartition, partition, and global) statistics *. 'AUTO'- determines the granularity based on the partitioning type. This is the default value. *. 'DEFAULT' - gathers global and partition-level statistics. This option is obsolete, and while currently supported, it is included in the documentation for legacy reasons only. You should use the 'GLOBAL AND PARTITION' for this functionality. Note that the default value is now 'AUTO'. *. 'GLOBAL' - gathers global statistics *. 'GLOBAL AND PARTITION' - gathers the global and partition level statistics. No subpartition level statistics are gathered even if it is a composite partitioned object. *. 'PARTITION '- gathers partition-level statistics *. 'SUBPARTITION' - gathers subpartition-level statistics. | |
PUBLISH | This value determines whether or not newly gathered statistics will be published once the gather job has completed. Prior to Prior to Oracle Database 11g, Release 1 (11.1), once a statistic gathering job completed the new statistics were automatically published into the dictionary tables. The user now has the ability to gather statistics but not publish them immediately. This allows the DBA to test the new statistics before publishing them. | |
INCREMENTAL | his value determines whether or not the global statistics of a partitioned table will be maintained without doing a full table scan. With partitioned tables it is very common to load new data into a new partition. As new partitions are added and data loaded, the global table statistics need to be kept up to date. Oracle will update the global table statistics by scanning only the partitions that have been changed instead of the entire table if the following conditions hold: *. the INCREMENTAL value for the partitioned table is set to TRUE; *. the PUBLISH value for the partitioned table is set to TRUE; *. the user specifies AUTO_SAMPLE_SIZE for ESTIMATE_PERCENT and AUTO for GRANULARITY when gathering statistics on the table. | |
STALE_PERCENT | This value determines the percentage of rows in a table that have to change before the statistics on that table are deemed stale and should be regathered. The default value is 10%. | |
ownname | Owner name | |
tabname | Table name |
Publish 된 통계정보 저장 테이블 | Pending 된 통계정보 저장 테이블 |
---|---|
USER_TAB_STATISTICS | USER_TAB_PENDING_STATS |
USER_IND_STATISTICS | USER_IND_PENDING_STATS |
-- 1. TABLE
CREATE TABLE XSOFT_T (VAL NUMBER);
INSERT INTO XSOFT_T
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 1000;
COMMIT;
-- 2. INDEX
CREATE INDEX XSOFT_T_N1 ON XSOFT_T(VAL);
-- 3. 통계정보 생성
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>USER, TABNAME=>'XSOFT_T') ;
-- 4. USER_TAB_STATISTICS 확인
SELECT *
FROM USER_TAB_STATISTICS
WHERE TABLE_NAME = 'XSOFT_T'
;
COLUMN VALUE
------------------------------ ------------------------------
TABLE_NAME XSOFT_T
PARTITION_NAME
PARTITION_POSITION
SUBPARTITION_NAME
SUBPARTITION_POSITION
OBJECT_TYPE TABLE
NUM_ROWS 1000
BLOCKS 5
EMPTY_BLOCKS 0
AVG_SPACE 0
CHAIN_CNT 0
AVG_ROW_LEN 4
AVG_SPACE_FREELIST_BLOCKS 0
NUM_FREELIST_BLOCKS 0
AVG_CACHED_BLOCKS
AVG_CACHE_HIT_RATIO
SAMPLE_SIZE 1000
LAST_ANALYZED 2011-10-12 오후 6:28:33
GLOBAL_STATS YES
USER_STATS NO
STATTYPE_LOCKED
STALE_STATS NO
;
-- 5. USER_IND_STATISTICS 확인
SELECT *
FROM USER_IND_STATISTICS
WHERE TABLE_NAME = 'XSOFT_T'
;
COLUMN VALUE
------------------------------ -----------------------------
INDEX_NAME XSOFT_N1
TABLE_OWNER USER
TABLE_NAME XSOFT_T
PARTITION_NAME
PARTITION_POSITION
SUBPARTITION_NAME
SUBPARTITION_POSITION
OBJECT_TYPE INDEX
BLEVEL 1
LEAF_BLOCKS 2
DISTINCT_KEYS 1000
AVG_LEAF_BLOCKS_PER_KEY 1
AVG_DATA_BLOCKS_PER_KEY 1
CLUSTERING_FACTOR 2
NUM_ROWS 1000
AVG_CACHED_BLOCKS
AVG_CACHE_HIT_RATIO
SAMPLE_SIZE 1000
LAST_ANALYZED 2011-10-12 오후 6:28:33
GLOBAL_STATS YES
USER_STATS NO
STATTYPE_LOCKED
STALE_STATS NO
;
-- 6. USER_TAB_PENDING_STATS 확인
SELECT *
FROM USER_TAB_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
;
COLUMN VALUE
------------------------------ ------------------------------
TABLE_NAME
PARTITION_NAME
SUBPARTITION_NAME
NUM_ROWS
BLOCKS
AVG_ROW_LEN
SAMPLE_SIZE
LAST_ANALYZED
;
-- 7. USER_IND_PENDING_STATS 확인
SELECT *
FROM USER_IND_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
;
COLUMN VALUE
------------------------------ ------------------------------
INDEX_NAME
TABLE_OWNER
TABLE_NAME
PARTITION_NAME
SUBPARTITION_NAME
BLEVEL
LEAF_BLOCKS
DISTINCT_KEYS
AVG_LEAF_BLOCKS_PER_KEY
AVG_DATA_BLOCKS_PER_KEY
CLUSTERING_FACTOR
NUM_ROWS
SAMPLE_SIZE
LAST_ANALYZED
EXEC DBMS_STATS.SET_TABLE_PREFS('SH', 'CUSTOMERS', 'PUBLISH', 'FALSE');
DBMS_STATS.SET_TABLE_PREFS (ownname IN VARCHAR2,
tabname IN VARCHAR2,
pname IN VARCHAR2,
pvalue IN VARCHAR2);
parameter | values | description |
---|---|---|
ownname | Owner name | |
tabname | Table name | |
pname | CASCADE | he value determines whether or not index statistics are collected as part of gathering table statistics. |
DEGREE | The value determines degree of parallelism used for gathering statistics. | |
ESTIMATE_PERCENT | The value determines the percentage of rows to estimate. The valid range is '0.000001,100'. Use the constant DBMS_STATS.AUTO_SAMPLE_SIZE to have Oracle determine the appropriate sample size for good statistics. This is the default. | |
METHOD_OPT | The value controls column statistics collection and histogram creation. It accepts either of the following options, or both in combination: *. FOR ALL 'INDEXED / HIDDEN' COLUMNS 'size_clause' *. FOR COLUMNS 'size clause' column/attribute 'size_clause' ',column/attribute 'size_clause'...' size_clause is defined as size_clause := SIZE 'integer / REPEAT / AUTO / SKEWONLY' column is defined as column := column_name / (extension) | |
NO_INVALIDATE | he value controls the invalidation of dependent cursors of the tables for which statistics are being gathered. Does not invalidate the dependent cursors if set to TRUE. The procedure invalidates the dependent cursors immediately if set to FALSE. Use DBMS_STATS.AUTO_INVALIDATE to have Oracle decide when to invalidate dependent cursors. This is the default. | |
GRANULARITY | The value determines granularity of statistics to collect (only pertinent if the table is partitioned). *. 'ALL' - gathers all (subpartition, partition, and global) statistics *. 'AUTO'- determines the granularity based on the partitioning type. This is the default value. *. 'DEFAULT' - gathers global and partition-level statistics. This option is obsolete, and while currently supported, it is included in the documentation for legacy reasons only. You should use the 'GLOBAL AND PARTITION' for this functionality. Note that the default value is now 'AUTO'. *. 'GLOBAL' - gathers global statistics *. 'GLOBAL AND PARTITION' - gathers the global and partition level statistics. No subpartition level statistics are gathered even if it is a composite partitioned object. *. 'PARTITION '- gathers partition-level statistics *. 'SUBPARTITION' - gathers subpartition-level statistics. | |
PUBLISH | This value determines whether or not newly gathered statistics will be published once the gather job has completed. Prior to Prior to Oracle Database 11g, Release 1 (11.1), once a statistic gathering job completed the new statistics were automatically published into the dictionary tables. The user now has the ability to gather statistics but not publish them immediately. This allows the DBA to test the new statistics before publishing them. | |
INCREMENTAL | his value determines whether or not the global statistics of a partitioned table will be maintained without doing a full table scan. With partitioned tables it is very common to load new data into a new partition. As new partitions are added and data loaded, the global table statistics need to be kept up to date. Oracle will update the global table statistics by scanning only the partitions that have been changed instead of the entire table if the following conditions hold: *. the INCREMENTAL value for the partitioned table is set to TRUE; *. the PUBLISH value for the partitioned table is set to TRUE; *. the user specifies AUTO_SAMPLE_SIZE for ESTIMATE_PERCENT and AUTO for GRANULARITY when gathering statistics on the table. | |
STALE_PERCENT | This value determines the percentage of rows in a table that have to change before the statistics on that table are deemed stale and should be regathered. The default value is 10%. | |
pvalue | Preference value. If NULL is specified, it will set the Oracle default value. |
DBMS_STATS.SET_TABLE_PREFS('SH', 'SALES', 'CASCADE', 'DBMS_STATS.AUTO_CASCADE');
DBMS_STATS.SET_TABLE_PREFS('SH', 'SALES', 'ESTIMATE_PERCENT', '9');
DBMS_STATS.SET_TABLE_PREFS('SH', 'SALES', 'DEGREE', '99');
-- 1. XSOFT_T 테이블 PUBILSH -> PENDING 변경
EXEC DBMS_STATS.SET_TABLE_PREFS(USER, 'XSOFT_T', 'PUBLISH', 'FALSE');
-- 2. 통계정보 재생성
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>USER, TABNAME=>'XSOFT_T') ;
-- 3. USER_TAB_PENDING_STATS 확인
SELECT *
FROM USER_TAB_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
;
COLUMN VALUE
------------------------------ ------------------------
TABLE_NAME XSOFT_T
PARTITION_NAME
SUBPARTITION_NAME
NUM_ROWS 1000
BLOCKS 5
AVG_ROW_LEN 4
SAMPLE_SIZE 1000
LAST_ANALYZED 2011-10-12 오후 7:02:13
;
-- 4. USER_IND_PENDING_STATS 확인
SELECT *
FROM USER_IND_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
;
COLUMN VALUE
------------------------------ ----------------------------
INDEX_NAME XSOFT_N1
TABLE_OWNER USER
TABLE_NAME XSOFT_T
PARTITION_NAME
SUBPARTITION_NAME
BLEVEL
LEAF_BLOCKS 2
DISTINCT_KEYS 1000
AVG_LEAF_BLOCKS_PER_KEY 1
AVG_DATA_BLOCKS_PER_KEY 1
CLUSTERING_FACTOR 2
NUM_ROWS 1000
SAMPLE_SIZE 1000
LAST_ANALYZED 2011-10-12 오후 7:02:13
;
alter session set optimizer_pending_statistis = TRUE;
EXEC DBMS_STATS.PUBLISH_PENDING_STATS(NULL, NULL);
DBMS_STATS.PUBLISH_PENDING_STATS (ownname IN VARCHAR2 DEFAULT USER,
tabname IN VARCHAR2,
no_invalidate BOOLEAN DEFAULT to_no_invalidate_type(get_param('NO_INVALIDATE')),
force IN BOOLEAN DEFAULT FALSE);
parameter | description |
---|---|
ownname | Owner name |
tabname | Table name |
no_invalidate | Do not invalidate the dependent cursors if set to TRUE. The procedure invalidates the dependent cursors immediately if set to FALSE. Use DBMS_STATS.AUTO_INVALIDATE to have Oracle decide when to invalidate dependent cursors. This is the default. The default can be changed using the SET_PARAM Procedure. |
force | If TRUE, will override the lock |
DBMS_STATS.PUBLISH_PENDING_STATS ('SH', null);
EXEC DBMS_STATS.PUBLISH_PENDING_STATS('SH', 'CUSTOMERS');
SELECT DBMS_STATS.GET_PREFS('STALE_PERCENT', USER, 'XSOFT_T') STALE_PERCENT
FROM DUAL
;
STALE_PERCENT
---------------
10
-- 1. GLOBAL_STALE_PERCENT 값 변경
execute dbms_stats.set_global_prefs('STALE_PERCENT', '13');
-- 2. 데이터 확인
SELECT DBMS_STATS.GET_PREFS('STALE_PERCENT', USER, 'XSOFT_T') STALE_PERCENT
FROM DUAL
;
STALE_PERCENT
---------------
13
-- 1. LOCAL_STALE_PERCENT 값 변경
execute dbms_stats.set_table_prefs(USER, 'XSOFT_T', 'STALE_PERCENT', '65');
-- 2. 데이터 확인
SELECT DBMS_STATS.GET_PREFS('STALE_PERCENT', USER, 'XSOFT_T') STALE_PERCENT
FROM DUAL
;
STALE_PERCENT
---------------
65
-- 1. LOCAL_STALE_PERCENT 값 제거
execute dbms_stats.delete_table_prefs(USER, 'XSOFT_T', 'STALE_PERCENT');
-- 2. 데이터 확인
SELECT DBMS_STATS.GET_PREFS('STALE_PERCENT', USER, 'XSOFT_T') STALE_PERCENT
FROM DUAL
;
STALE_PERCENT
---------------
13
-- 1. GLOBAL_STALE_PERCENT 값 제거
execute dbms_stats.set_global_prefs('STALE_PERCENT', null);
-- 2. 데이터 확인
SELECT DBMS_STATS.GET_PREFS('STALE_PERCENT', USER, 'XSOFT_T') STALE_PERCENT
FROM DUAL
;
STALE_PERCENT
---------------
10
-- 1. XSOFT_T 테이블 PENDING -> PUBILSH 변경
EXEC DBMS_STATS.SET_TABLE_PREFS(USER, 'XSOFT_T', 'PUBLISH', 'TRUE');
-- 2. XSOFT_T 테이블 PUBILSH 여부 확인
SELECT DBMS_STATS.GET_PREFS('PUBLISH', USER, 'XSOFT_T') PUBLISH
FROM DUAL;
PUBLISH
--------
TRUE
-- 3. XSOFT_T 테이블 PUBILSH 통계정보 확인
SELECT *
FROM USER_TAB_STATISTICS
WHERE TABLE_NAME = 'XSOFT_T'
;
COLUMN VALUE
------------------------------ ---------------------------
TABLE_NAME XSOFT_T
PARTITION_NAME
PARTITION_POSITION
SUBPARTITION_NAME
SUBPARTITION_POSITION
OBJECT_TYPE TABLE
NUM_ROWS 1000
BLOCKS 5
EMPTY_BLOCKS 0
AVG_SPACE 0
CHAIN_CNT 0
AVG_ROW_LEN 4
AVG_SPACE_FREELIST_BLOCKS 0
NUM_FREELIST_BLOCKS 0
AVG_CACHED_BLOCKS
AVG_CACHE_HIT_RATIO
SAMPLE_SIZE 1000
LAST_ANALYZED 2011-10-12 오후 6:28:33
GLOBAL_STATS YES
USER_STATS NO
STATTYPE_LOCKED
STALE_STATS NO
;
-- 4. 데이터 INSERT(100% 증가)
INSERT INTO XSOFT_T
SELECT LEVEL + 1000
FROM DUAL
CONNECT BY LEVEL <= 1000;
COMMIT;
-- 5. XSOFT_T 테이블 PUBILSH 통계정보 재 확인(통계정보 자동갱신이 설정되어 있지 않아 갱신 안됨)
SELECT *
FROM USER_TAB_STATISTICS
WHERE TABLE_NAME = 'XSOFT_T'
;
COLUMN VALUE
------------------------------ ---------------------------
TABLE_NAME XSOFT_T
PARTITION_NAME
PARTITION_POSITION
SUBPARTITION_NAME
SUBPARTITION_POSITION
OBJECT_TYPE TABLE
NUM_ROWS 1000
BLOCKS 5
EMPTY_BLOCKS 0
AVG_SPACE 0
CHAIN_CNT 0
AVG_ROW_LEN 4
AVG_SPACE_FREELIST_BLOCKS 0
NUM_FREELIST_BLOCKS 0
AVG_CACHED_BLOCKS
AVG_CACHE_HIT_RATIO
SAMPLE_SIZE 1000
LAST_ANALYZED 2011-10-12 오후 6:28:33
GLOBAL_STATS YES
USER_STATS NO
STATTYPE_LOCKED
STALE_STATS NO
;
-- 1. 테이블 재생성
DROP TABLE XSOFT_T;
CREATE TABLE XSOFT_T (VAL_1 NUMBER,
VAL_2 NUMBER,
VAL_3 NUMBER,
VAL_4 NUMBER);
-- 2. 데이터 생성(분포도를 위해 NDV를 각각 10000, 1000, 100, 10으로 생성)
INSERT INTO XSOFT_T
SELECT LEVEL,
MOD(LEVEL, 10),
MOD(LEVEL, 100),
MOD(LEVEL, 1000)
FROM DUAL
CONNECT BY LEVEL <= 10000;
COMMIT;
-- 3. INDEX 생성
CREATE INDEX XSOFT_T_N1 ON XSOFT_T(VAL_1);
CREATE INDEX XSOFT_T_N2 ON XSOFT_T(VAL_2);
CREATE INDEX XSOFT_T_N3 ON XSOFT_T(VAL_3);
CREATE INDEX XSOFT_T_N4 ON XSOFT_T(VAL_4);
-- 4. global publish 확인
-- (현재 이 시스템에서는 Default가 PUBLISH 상태)
SELECT DBMS_STATS.GET_PREFS('PUBLISH') PUBLISH
FROM DUAL
;
PUBLISH
-------
TRUE
;
-- 5. local publish 확인
-- (Default가 PUBLISH 이므로 테이블도 Default로 PUBLISH)
SELECT DBMS_STATS.GET_PREFS('PUBLISH', USER, 'XSOFT_T') PUBLISH
FROM DUAL
;
PUBLISH
-------
TRUE
;
-- 6. XSOFT_T 테이블의 publish 통계정보 확인
-- 6-1) table
SELECT TABLE_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_ROWS,
BLOCKS,
AVG_ROW_LEN
FROM USER_TABLES
WHERE TABLE_NAME = 'XSOFT_T'
;
TABLE_NAME ANALYZE_TIME NUM_ROWS BLOCKS AVG_ROW_LEN
------------ ------------ ---------- ---------- -----------
XSOFT_T
;
-- 6-2) indexes
SELECT INDEX_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_ROWS,
LEAF_BLOCKS,
DISTINCT_KEYS
FROM USER_INDEXES
WHERE TABLE_NAME = 'XSOFT_T'
ORDER BY INDEX_NAME
;
INDEX_NAME ANALYZE_TIME NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS
------------ ------------ ---------- ----------- -------------
XSOFT_T_N1
XSOFT_T_N2
XSOFT_T_N3
XSOFT_T_N4
;
-- 6-3) columns
SELECT COLUMN_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_DISTINCT,
NUM_NULLS,
DENSITY
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'XSOFT_T'
ORDER BY COLUMN_NAME
;
COLUMN_NAME ANALYZE_TIME NUM_DISTINCT NUM_NULLS DENSITY
------------ ------------ ------------ ---------- ----------
VAL_1
VAL_2
VAL_3
VAL_4
;
-- 7. XSOFT_T 테이블의 pending 통계정보 확인
-- 7-1) tables
SELECT TABLE_NAME,
LAST_ANALYZED "analyze time",
NUM_ROWS,
BLOCKS,
AVG_ROW_LEN
FROM USER_TAB_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
;
no rows selected
;
-- 7-2) indexes
SELECT INDEX_NAME,
LAST_ANALYZED "analyze time",
NUM_ROWS,
LEAF_BLOCKS,
DISTINCT_KEYS
FROM USER_IND_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
ORDER BY INDEX_NAME
;
no rows selected
;
-- 7-3) columns
SELECT COLUMN_NAME,
LAST_ANALYZED "analyze time",
NUM_DISTINCT,
NUM_NULLS,
DENSITY
FROM USER_COL_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
ORDER BY COLUMN_NAME
;
no rows selected
;
-- 8. XSOFT_T 테이블 통계정보 publish -> pending 변경
EXEC DBMS_STATS.SET_TABLE_PREFS(USER, 'XSOFT_T', 'PUBLISH', 'FALSE');
-- 9. XSOFT_T 테이블 pending 확인
SELECT DBMS_STATS.GET_PREFS('PUBLISH', USER, 'XSOFT_T') PUBLISH
FROM DUAL
;
PUBLISH
-------
FALSE
;
-- 10. XSOFT_T 테이블 통계정보 생성
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>USER, TABNAME=>'XSOFT_T');
-- 11. XSOFT_T 테이블 publish 통계정보 확인
-- (XSOFT_T 테이블을 PENDING으로 변경했으므로 PUBLISH에서는 갱신 안됨)
-- 11-1) table
SELECT TABLE_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_ROWS,
BLOCKS,
AVG_ROW_LEN
FROM USER_TABLES
WHERE TABLE_NAME = 'XSOFT_T'
;
TABLE_NAME ANALYZE_TIME NUM_ROWS BLOCKS AVG_ROW_LEN
------------ ------------ ---------- ---------- -----------
XSOFT_T
;
-- 11-2) indexes
SELECT INDEX_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_ROWS,
LEAF_BLOCKS,
DISTINCT_KEYS
FROM USER_INDEXES
WHERE TABLE_NAME = 'XSOFT_T'
ORDER BY INDEX_NAME
;
INDEX_NAME ANALYZE_TIME NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS
------------ ------------ ---------- ----------- -------------
XSOFT_T_N1
XSOFT_T_N2
XSOFT_T_N3
XSOFT_T_N4
;
-- 11-3) columns
SELECT COLUMN_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_DISTINCT,
NUM_NULLS,
DENSITY
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'XSOFT_T'
ORDER BY COLUMN_NAME
;
COLUMN_NAME ANALYZE_TIME NUM_DISTINCT NUM_NULLS DENSITY
------------ ------------ ------------ ---------- ----------
VAL_1
VAL_2
VAL_3
VAL_4
;
-- 12. XSOFT_T 테이블 pending 통계정보 확인
-- (XSOFT_T 테이블을 PENDING이므로 확인 가능)
-- 12-1) tables
SELECT TABLE_NAME,
LAST_ANALYZED "analyze time",
NUM_ROWS,
BLOCKS,
AVG_ROW_LEN
FROM USER_TAB_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
;
TABLE_NAME analyze time NUM_ROWS BLOCKS AVG_ROW_LEN
------------- ------------ ---------- ---------- -----------
XSOFT_T 13-OCT-11 10000 28 14
;
-- 12-2) indexes
SELECT INDEX_NAME,
LAST_ANALYZED "analyze time",
NUM_ROWS,
LEAF_BLOCKS,
DISTINCT_KEYS
FROM USER_IND_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
ORDER BY INDEX_NAME
;
INDEX_NAME analyze time NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS
------------- ------------ ---------- ----------- -------------
XSOFT_T_N1 13-OCT-11 10000 21 10000
XSOFT_T_N2 13-OCT-11 10000 20 10
XSOFT_T_N3 13-OCT-11 10000 20 100
XSOFT_T_N4 13-OCT-11 10000 21 1000
;
-- 12-3) columns
SELECT COLUMN_NAME,
LAST_ANALYZED "analyze time",
NUM_DISTINCT,
NUM_NULLS,
DENSITY
FROM USER_COL_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
ORDER BY COLUMN_NAME
;
COLUMN_NAME analyze time NUM_DISTINCT NUM_NULLS DENSITY
------------- ------------ ------------ ---------- ----------
VAL_1 13-OCT-11 10000 0 .0001
VAL_2 13-OCT-11 10 0 .1
VAL_3 13-OCT-11 100 0 .01
VAL_4 13-OCT-11 1000 0 .001
alter session set optimizer_use_pending_statistics = false;
alter session set optimizer_dynamic_sampling = 0;
-- 1. VAL_2 조건 사용한 실행계획 확인
-- (dynamic sampling을 사용 안하기 때문에, 예상 rows는 1건)
-- (그리고 NDV 값을 모르기 때문에 FULL TABLE SCAN이 더 좋음에도 INDEX를 사용함)
EXPLAIN PLAN FOR
SELECT *
FROM XSOFT_T
WHERE VAL_2 = 1
;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 52 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| XSOFT_T | 1 | 52 | 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | XSOFT_T_N2 | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("VAL_2"=1)
;
-- 2. pending 통계정보 사용
alter session set optimizer_use_pending_statistics = true;
-- 3. 실행계획 다시 확인
EXPLAIN PLAN FOR
SELECT *
FROM XSOFT_T
WHERE VAL_2 = 1
;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1000 | 14000 | 9 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| XSOFT_T | 1000 | 14000 | 9 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("VAL_2"=1)
EXEC DBMS_STATS.PUBLISH_PENDING_STATS(USER, 'XSOFT_T');
-- 1. publish 통계정보 확인
-- 1-1) table
SELECT TABLE_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_ROWS,
BLOCKS,
AVG_ROW_LEN
FROM USER_TABLES
WHERE TABLE_NAME = 'XSOFT_T'
;
TABLE_NAME ANALYZE_TIME NUM_ROWS BLOCKS AVG_ROW_LEN
------------- ------------ ---------- ---------- -----------
XSOFT_T 13-OCT-11 10000 28 14
;
-- 1-2) indexes
SELECT INDEX_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_ROWS,
LEAF_BLOCKS,
DISTINCT_KEYS
FROM USER_INDEXES
WHERE TABLE_NAME = 'XSOFT_T'
ORDER BY INDEX_NAME
;
INDEX_NAME ANALYZE_TIME NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS
------------- ------------ ---------- ----------- -------------
XSOFT_T_N1 13-OCT-11 10000 21 10000
XSOFT_T_N2 13-OCT-11 10000 20 10
XSOFT_T_N3 13-OCT-11 10000 20 100
XSOFT_T_N4 13-OCT-11 10000 21 1000
;
-- 1-3) columns
SELECT COLUMN_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_DISTINCT,
NUM_NULLS,
DENSITY
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'XSOFT_T'
ORDER BY COLUMN_NAME
;
COLUMN_NAME ANALYZE_TIME NUM_DISTINCT NUM_NULLS DENSITY
------------- ------------ ------------ ---------- ----------
VAL_1 13-OCT-11 10000 0 .0001
VAL_2 13-OCT-11 10 0 .1
VAL_3 13-OCT-11 100 0 .01
VAL_4 13-OCT-11 1000 0 .001
-- 2. pending 통계정보 확인
-- (pending -> publish로 변경하면 자동으로 pending 데이터는 삭제됨)
-- 2-1) tables
SELECT TABLE_NAME,
LAST_ANALYZED "analyze time",
NUM_ROWS,
BLOCKS,
AVG_ROW_LEN
FROM USER_TAB_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
;
no rows selected
;
-- 2-2) indexes
SELECT INDEX_NAME,
LAST_ANALYZED "analyze time",
NUM_ROWS,
LEAF_BLOCKS,
DISTINCT_KEYS
FROM USER_IND_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
ORDER BY INDEX_NAME
;
no rows selected
;
-- 2-3) columns
SELECT COLUMN_NAME,
LAST_ANALYZED "analyze time",
NUM_DISTINCT,
NUM_NULLS,
DENSITY
FROM USER_COL_PENDING_STATS
WHERE TABLE_NAME = 'XSOFT_T'
AND PARTITION_NAME IS NULL
ORDER BY COLUMN_NAME
;
no rows selected
-- 1. 통계정보 삭제
exec dbms_stats.delete_table_stats(USER, 'XSOFT_T');
-- 2. public 통계정보 확인
-- 2-1) table
SELECT TABLE_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_ROWS,
BLOCKS,
AVG_ROW_LEN
FROM USER_TABLES
WHERE TABLE_NAME = 'XSOFT_T'
;
TABLE_NAME ANALYZE_TIME NUM_ROWS BLOCKS AVG_ROW_LEN
------------- ------------ ---------- ---------- -----------
XSOFT_T
;
-- 2-2) indexes
SELECT INDEX_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_ROWS,
LEAF_BLOCKS,
DISTINCT_KEYS
FROM USER_INDEXES
WHERE TABLE_NAME = 'XSOFT_T'
ORDER BY INDEX_NAME
;
INDEX_NAME ANALYZE_TIME NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS
------------- ------------ ---------- ----------- -------------
XSOFT_T_N1
XSOFT_T_N2
XSOFT_T_N3
XSOFT_T_N4
;
-- 2-3) columns
SELECT COLUMN_NAME,
LAST_ANALYZED ANALYZE_TIME,
NUM_DISTINCT,
NUM_NULLS,
DENSITY
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'XSOFT_T'
ORDER BY COLUMN_NAME
;
COLUMN_NAME ANALYZE_TIME NUM_DISTINCT NUM_NULLS DENSITY
------------- ------------ ------------ ---------- ----------
VAL_1
VAL_2
VAL_3
VAL_4
참고 사이트