1. 创建测试表并插入有特殊数据分布的数据
-- 创建测试表
CREATE TABLE DM_STATS_TEST (
id INT,
category VARCHAR(10),
value INT);
-- 插入1000行数据,制造特殊分布:
-
category='A':990行(占99%)
-
category='B':10行(占1%)
INSERT INTO DM_STATS_TEST
SELECT LEVEL, 'A', LEVEL FROM DUAL CONNECT BY LEVEL <= 990
UNION ALL
SELECT 990+LEVEL, 'B', 1000+LEVEL FROM DUAL CONNECT BY LEVEL <= 10;
COMMIT;
在 CATEGORY 字段上创建一个索引
CREATE OR REPLACE INDEX "EXAM"."IDX_CATEGORY" ON "EXAM"."DM_STATS_TEST"("CATEGORY" ASC) STORAGE(ON "MAIN", CLUSTERBTR) ;
2. 执行一个查询并查看执行计划
SELECT * FROM DM_STATS_TEST WHERE CATEGORY =:VAR;
<===查询 B
1 #NSET2: [1, 25, 68]
2 #PRJT2: [1, 25, 68]; exp_num(4), is_atom(FALSE)
3 #BLKUP2: [1, 25, 68]; IDX_CATEGORY(DM_STATS_TEST)
4 #SSEK2: [1, 25, 68]; scan_type(ASC), IDX_CATEGORY(DM_STATS_TEST), scan_range[exp_param(no:0),exp_param(no:0)], is_global(0)·
SELECT PLN_ADDR,HASH_VALUE,SQLSTR,RT_METHOD,N_SUBPLNS,PHD_TIME FROM V$SQL_PLAN WHERE SQLSTR LIKE '%SELECT * FROM DM_STATS_TEST WHERE CATEGORY%'
and lower(SQLSTR) NOT LIKE '%v$%';
PLN_ADDR HASH_VALUE SQLSTR RT_METHOD N_SUBPLNS PHD_TIME
0x00000000797F7810 315894334 SELECT * FROM DM_STATS_TEST WHERE CATEGORY =:VAR; 0x00000000797F7E28 0 2026-01-06 15:37:00
3 - 使用常用方式收集的统计信息
DBMS_STATS.GATHER_TABLE_STATS('EXAM','DM_STATS_TEST',null,100,TRUE,'FOR ALL COLUMNS SIZE AUTO',2);
4 - 再次执行相同查询并查看执行计划
SELECT * FROM DM_STATS_TEST WHERE CATEGORY =:VAR;
<===查询 B
1 #NSET2: [1, 500, 68]
2 #PRJT2: [1, 500, 68]; exp_num(4), is_atom(FALSE)
3 #SLCT2: [1, 500, 68]; DM_STATS_TEST.category = exp_param(no:0) SLCT_PUSHDOWN(TRUE)
4 #CSCN2: [1, 1000, 68]; INDEX33555640(DM_STATS_TEST) NEED_SLCT(TRUE); btr_scan(1)
SELECT PLN_ADDR,HASH_VALUE,SQLSTR,RT_METHOD,N_SUBPLNS,PHD_TIME FROM V$SQL_PLAN WHERE SQLSTR LIKE '%SELECT * FROM DM_STATS_TEST WHERE CATEGORY%'
and lower(SQLSTR) NOT LIKE '%v$%';
PLN_ADDR HASH_VALUE SQLSTR RT_METHOD N_SUBPLNS PHD_TIME
0x00000000797F7810 315894334 SELECT * FROM DM_STATS_TEST WHERE CATEGORY =:VAR; 0x00000000797F7E28 0 2026-01-06 15:37:00
5 - 指定执行计划失效的统计信息
begin
DBMS_STATS.GATHER_TABLE_STATS (
ownname => 'EXAM',
tabname => 'DM_STATS_TEST',
method_opt =>'FOR ALL COLUMNS SIZE AUTO',
granularity => 'ALL',
no_invalidate=>FALSE,
cascade => true,
force => true);
end;
/
6 - 直接检查内存中的执行计划
SELECT PLN_ADDR,HASH_VALUE,SQLSTR,RT_METHOD,N_SUBPLNS,PHD_TIME FROM V$SQL_PLAN WHERE SQLSTR LIKE '%SELECT * FROM DM_STATS_TEST WHERE CATEGORY%'
and lower(SQLSTR) NOT LIKE '%v$%';
空 <===其实到这就说明执行计划已经并清除了。
7 - 再次执行相同查询并查看执行计划
SELECT * FROM DM_STATS_TEST WHERE CATEGORY =:VAR;
<===查询 B
1 #NSET2: [1, 500, 68]
2 #PRJT2: [1, 500, 68]; exp_num(4), is_atom(FALSE)
3 #SLCT2: [1, 500, 68]; DM_STATS_TEST.category = exp_param(no:0) SLCT_PUSHDOWN(TRUE)
4 #CSCN2: [1, 1000, 68]; INDEX33555640(DM_STATS_TEST) NEED_SLCT(TRUE); btr_scan(1)
SELECT PLN_ADDR,HASH_VALUE,SQLSTR,RT_METHOD,N_SUBPLNS,PHD_TIME FROM V$SQL_PLAN WHERE SQLSTR LIKE '%SELECT * FROM DM_STATS_TEST WHERE CATEGORY%'
and lower(SQLSTR) NOT LIKE '%v$%';
PLN_ADDR HASH_VALUE SQLSTR RT_METHOD N_SUBPLNS PHD_TIME
0x0000000079720A10 315894334 SELECT * FROM DM_STATS_TEST WHERE CATEGORY =:VAR; 0x0000000079721028 0 2026-01-06 15:46:54
欢迎访问达梦技术分享社区 ECO