版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xxzhaobb/article/details/88551233
设置优化器的统计信息,从而欺骗优化器,让优化器走不同的执行计划(这里有部分没有测试成功,文档上的未人工干预的时候,走的执行计划是全表扫描,测试还是走的索引,人工干预后,走的还是索引,不过优化器评估的rows有很大变化,了解了这个原理)。
- - 创建表和索引,并插入1条数据
BB@test>CREATE TABLE contractors (
con_id NUMBER,
last_name VARCHAR2(50),
salary NUMBER,
CONSTRAINT cond_id_pk PRIMARY KEY(con_id) ); 2 3 4 5
Table created.
BB@test>CREATE INDEX salary_ix ON contractors(salary);
Index created.
BB@test>INSERT INTO contractors VALUES (8, 'JONES',1000);
1 row created.
BB@test>commit;
Commit complete.
BB@test>
-- 收集统计信息,并查看统计信息情况
BB@test>EXECUTE DBMS_STATS.GATHER_TABLE_STATS( user, tabname => 'CONTRACTORS' );
PL/SQL procedure successfully completed.
BB@test>SELECT NUM_ROWS FROM USER_TABLES WHERE TABLE_NAME = 'CONTRACTORS';
NUM_ROWS
----------
1
BB@test>SELECT NUM_ROWS FROM USER_INDEXES WHERE INDEX_NAME = 'SALARY_IX';
NUM_ROWS
----------
1
-- 进行查询,查看执行计划
BB@test>SELECT /*+ dynamic_sampling(contractors 0) */ *
FROM contractors
WHERE salary = 1000; 2 3
CON_ID LAST_NAME SALARY
---------- -------------------------------------------------- ----------
8 JONES 1000
BB@test>SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID dx4g7f3zzb3kk, child number 0
-------------------------------------
SELECT /*+ dynamic_sampling(contractors 0) */ * FROM contractors WHERE
salary = 1000
Plan hash value: 996794789
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| CONTRACTORS | 1 | 12 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | SALARY_IX | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("SALARY"=1000)
20 rows selected.
BB@test>
-- 人工设置,将统计信息里面的行设置成2000,块10个,并查看统计信息,优化器认为有2000个行,10个块。
BB@test>BEGIN
DBMS_STATS.SET_TABLE_STATS(
ownname => user
, tabname => 'CONTRACTORS'
, numrows => 2000
, numblks => 10 );
END; 2 3 4 5 6 7
8 /
PL/SQL procedure successfully completed.
BB@test>BEGIN
DBMS_STATS.SET_INDEX_STATS(
ownname => user
, indname => 'SALARY_IX'
, numrows => 2000 );
END; 2 3 4 5 6
7 /
PL/SQL procedure successfully completed.
BB@test>SELECT NUM_ROWS FROM USER_TABLES WHERE TABLE_NAME = 'CONTRACTORS';
NUM_ROWS
----------
2000
BB@test>SELECT NUM_ROWS FROM USER_INDEXES WHERE INDEX_NAME = 'SALARY_IX';
NUM_ROWS
----------
2000
BB@test>
--
BB@test>ALTER SYSTEM FLUSH SHARED_POOL;
System altered.
BB@test>SELECT /*+ dynamic_sampling(contractors 0) */ *
FROM contractors
WHERE salary = 1000; 2 3
Execution Plan
----------------------------------------------------------
Plan hash value: 996794789
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2000 | 24000 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| CONTRACTORS | 2000 | 24000 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | SALARY_IX | 2000 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
-- 删除掉统计信息
BB@test>exec dbms_stats.delete_table_stats(user,'CONTRACTORS');
PL/SQL procedure successfully completed.
-- 虽然未测试成功,但原理已了解。
end