開啟 10046 trace 的 Session,Oracle 會將後續 SQL 標記為需重新優化,導致 執行計畫與未 Trace 時不同,分析結果失真。
-- 建立資料傾斜表
CREATE TABLE t1 (value NUMBER, flag NUMBER, pad VARCHAR2(2000));
INSERT INTO t1 SELECT rownum, MOD(rownum,2000), LPAD('x',1000,'x') FROM dba_objects;
INSERT INTO t1 SELECT rownum, 3000, LPAD('x',1000,'x') FROM dba_objects WHERE rownum <= 10000;
COMMIT;
CREATE INDEX t1_idx ON t1(flag);
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'T1',CASCADE=>TRUE,METHOD_OPT=>'FOR ALL INDEXED COLUMNS');
-- FLAG 欄位有 2030 個 distinct value,並建立直方圖 (75 buckets)
SELECT /*+ testsql */ SUM(value) FROM t1 WHERE flag = :v_flag;
ALTER SESSION SET TIMED_STATISTICS = TRUE; ALTER SESSION SET MAX_DUMP_FILE_SIZE = UNLIMITED; ALTER SESSION SET TRACEFILE_IDENTIFIER = 'MY_TRACE_20240101';
ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT FOREVER, LEVEL 12';
ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';
SELECT p.spid
FROM v$process p, v$session s
WHERE p.addr = s.paddr AND s.sid = SYS_CONTEXT('USERENV','SID');
檔案位於 USER_DUMP_DEST 或 BACKGROUND_DUMP_DEST,檔名含 spid 與 TRACEFILE_IDENTIFIER。tkprof trace.trc out.txt EXPLAIN=user/pass SYS=NO SORT=EXEELA,FCHELA。-- 方法一:DBMS_SUPPORT (推薦,需安裝) EXEC SYS.DBMS_SUPPORT.START_TRACE_IN_SESSION(sid, serial#, WAITS=>TRUE, BINDS=>TRUE); -- ... 運行應用 ... EXEC SYS.DBMS_SUPPORT.STOP_TRACE_IN_SESSION(sid, serial#); -- 方法二:DBMS_SYSTEM (通用) EXEC SYS.DBMS_SYSTEM.SET_EV(sid, serial#, 10046, 12, ''); -- ... 運行應用 ... EXEC SYS.DBMS_SYSTEM.SET_EV(sid, serial#, 10046, 0, '');
SQL Trace 是效能調優利器,但 啟用 Trace 本身會改變行為。務必先暖機固定計畫,再開啟 Trace,才能獲得真實可信的診斷資料。