不修改sql文本情況下,改變其執行計劃
不修改sql文本情況下,改變其執行計劃
可以使用sql profile和spm(sql plan manage),本文主要介紹SPM方式
sql profile參考sql profile固定執行計劃
步驟
1.手動生成SQL Plan Baseline
DECLARE
V_TEMP NUMBER;
BEGIN
V_TEMP :=
DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (SQL_ID => '原目标的sql_id',
PLAN_HASH_VALUE => 原目标sql的执行计划HASH值);
END;
2.改寫原SQL,加入hint,生成正確的執行計劃
-- SQL_ID和PLAN HASH VALUE可以在v$sql查找
-- SQL_HANDLE可以在DBA_DBA_SQL_PLAN_BASELINES中查找
DECLARE
V_TEMP NUMBER;
BEGIN
V_TEMP :=
DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (
SQL_ID => '改写SQL的SQL_ID',
PLAN_HASH_VALUE => 改写SQL执行计划HASH值,
SQL_HANDLE => '第一步生成的HANDLE');
END;
3.刪除第一步生成的SQL Plan Baseline
DECLARE
V_TEMP NUMBER;
BEGIN
V_TEMP :=
DBMS_SPM.DROP_SQL_PLAN_BASELINE (
SQL_HANDLE => '原目标HANDLE',
PLAN_NAME => '原目标PLAN_NAME');
END;
實驗
1.創建測試環境
CREATE TABLE TEST_SPM AS SELECT * FROM DBA_OBJECTS;
CREATE INDEX IX_TEST_SPM_OBJECT_ID ON TEST_SPM(OBJECT_ID);
2.構造原SQL並查看執行計劃
SELECT /*+NO_INDEX(TEST_SPM IX_TEST_SPM_OBJECT_ID)*/* FROM TEST_SPM WHERE OBJECT_ID=10;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
3.生成原SQL的SQL Plan Baseline
-- 生成
DECLARE
V_TEMP NUMBER;
BEGIN
V_TEMP :=
DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (SQL_ID => 'cjdf02m61dsd9',
PLAN_HASH_VALUE => 1145642998);
END;
-- 查看,因為數據庫的cursor_sharing為force,所以值被替代為變量
SELECT SQL_HANDLE,PLAN_NAME,SUBSTR(SQL_TEXT,0,100) SQL_TEXT FROM DBA_SQL_PLAN_BASELINES
4.修改sql並查看執行計劃
SELECT /*+INDEX(TEST_SPM IX_TEST_SPM_OBJECT_ID)*/* FROM TEST_SPM WHERE OBJECT_ID=10;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
5.用修改後的SQL的SQL_ID,PLAN HASH VALUE和原SQL的SQL HANDLE生成新的SQL PLAN BASELINE
-- 生成
DECLARE
V_TEMP NUMBER;
BEGIN
V_TEMP :=
DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE (
SQL_ID => 'cju4dakqwvft7',
PLAN_HASH_VALUE => 3777949824,
SQL_HANDLE => 'SQL_9fa71106593b209e');
END;
-- 查看
SELECT SQL_HANDLE,PLAN_NAME,TO_CHAR(SUBSTR(SQL_TEXT,0,100)) SQL_TEXT FROM DBA_SQL_PLAN_BASELINES;
6.刪除原SQL的SQL PLAN BASELINE
DECLARE
V_TEMP NUMBER;
BEGIN
V_TEMP :=
DBMS_SPM.DROP_SQL_PLAN_BASELINE (
SQL_HANDLE => 'SQL_9fa71106593b209e',
PLAN_NAME => 'SQL_PLAN_9z9sj0tcmq84yeb1890ae');
END;
7.查看原SQL的執行計劃
SELECT /*+NO_INDEX(TEST_SPM IX_TEST_SPM_OBJECT_ID)*/* FROM TEST_SPM WHERE OBJECT_ID=10;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
2019-09-09 记一次使用logmnr查找操作人流程