某企业征信Oracle数据库跑批耗时较长问题简述分析报告

1. 分析及解决方案概述

分析原因

  • 由于对跑批涉及的表在周末6点前进行了清数,Oracle周末自动收集统计信息的时间为早上6点,此时的表内数据量为0,导致对该表的执行计划发生了变化。因此在下午跑批过程中走的错误的执行计划,导致数据库中出现大量的排序操作或者使用临时表来存储中间结果,从而消耗大量的临时表空间,最终出现临时表空间不足的报错。

解决方案

  • 恢复该表的统计信息到6点自动收集统计信息之前,使该表的执行计划恢复到6点收集统计信息前。

2. 问题描述

  • 2024年4月21日18时20分,企业征信项目打来电话,说他们的跑批已经跑了40分钟还未结束,平时最多只跑20分钟,询问是否数据库出了故障问题。询问跑批涉及表数据量是否发生较大变化,项目人员回答数据量没有什么较大变化,最后排查是上午从核心提数对跑批涉及表进行了重新导数,虽然重新导数前后数据库看起来不大,但是过程中表有大量的删数和插数操作,且操作后没有收集统计信息。
操作系统版本RHEL 7
数据库架构RAC集群
数据库版本19.5.0

3. 问题分析

3.1 问题现象

跑批语句执行了近一个小时,语句还是没有跑过去,在后台查看当前执行sql,发现当前的等待事件在write temp,查看临时表空间90个G基本已经使用完了,随即先停止跑批任务:

1 手动SQL_MONITOR生成SQL监视报告
set linesize 500 pagesize 50000 long 999999 longchunksize 999999 
select dbms_sqltune.report_sql_monitor(sql_id => '&sql_id') from dual;
2查看表的统计信息历史
select o.owner, o.object_name, o.object_id, h.savtime, h.rowcnt, h.avgrln, h.analyzetimefrom dba_objects oleft join sys.wri$_optstat_tab_history hon o.object_id = h.obj#where o.owner = '用户名'and o.object_name in ('表名')order by o.object_id, h.savtime

通过表的统计信息历史可以看到该表在4月20号对表进行过统计分析,并在4月21日下午6点保存统计信息,在对表进行统计分析时表中的行数为0,应该时业务在跑批前将表清空过并重新从核心提数导入表中。因为此时表中没有数据,所以在进行统计分析后执行计划就会做出改变。

3 修改执行计划的方式
3.1.1 恢复该表的统计信息到指定时间点
exec dbms_stats.restore_table_stats(ownname => '用户名’, tabname =>'表名', as_of_timestamp => '31-JAN-20 11.23.06.652667 AM +08:00');
3.1.2 重新绑定执行计划
SPO coe_xfr_sql_profile.log;
SET DEF ON TERM OFF ECHO ON FEED OFF VER OFF HEA ON LIN 2000 PAGES 100 LONG 8000000 LONGC 800000 TRIMS ON TI OFF TIMI OFF SERVEROUT ON SIZE 1000000 NUMF "" SQLP SQL>;
SET SERVEROUT ON SIZE UNL;
REM
REM $Header: 215187.1 coe_xfr_sql_profile.sql 11.4.5.5 2013/03/01 carlos.sierra $
REM
REM Copyright (c) 2000-2013, Oracle Corporation. All rights reserved.
REM
REM AUTHOR
REM   carlos.sierra@oracle.com
REM
REM SCRIPT
REM   coe_xfr_sql_profile.sql
REM
REM DESCRIPTION
REM   This script generates another that contains the commands to
REM   create a manual custom SQL Profile out of a known plan from
REM   memory or AWR. The manual custom profile can be implemented
REM   into the same SOURCE system where the plan was retrieved,
REM   or into another similar TARGET system that has same schema
REM   objects referenced by the SQL that generated the known plan.
REM
REM PRE-REQUISITES
REM   1. Oracle Tuning Pack license.
REM
REM PARAMETERS
REM   1. SQL_ID (required)
REM   2. Plan Hash Value for which a manual custom SQL Profile is
REM      needed (required). A list of known plans is presented.
REM      You may choose from list provided or enter a valid phv
REM      from a version of the SQL modified with Hints.
REM
REM EXECUTION
REM   1. Connect into SQL*Plus as user with access to data dictionary.
REM      Do not use SYS.
REM   2. Execute script coe_xfr_sql_profile.sql passing SQL_ID and
REM      plan hash value (parameters can be passed inline or until
REM      requested).
REM
REM EXAMPLE
REM   # sqlplus system
REM   SQL> START coe_xfr_sql_profile.sql [SQL_ID] [PLAN_HASH_VALUE];
REM   SQL> START coe_xfr_sql_profile.sql gnjy0mn4y9pbm 2055843663;
REM   SQL> START coe_xfr_sql_profile.sql gnjy0mn4y9pbm;
REM   SQL> START coe_xfr_sql_profile.sql;
REM
REM NOTES
REM   1. For possible errors see coe_xfr_sql_profile.log
REM   2. If SQLT is installed in SOURCE, you can use instead:
REM      sqlt/utl/sqltprofile.sql
REM   3. Be aware that using DBMS_SQLTUNE requires a license for
REM      Oracle Tuning Pack.
REM   4. Use a DBA user but not SYS.
REM   5. If you get "ORA-06532: Subscript outside of limit, ORA-06512: at line 1"
REM      Then you may consider this change (only in a test and disposable system):
REM      create or replace TYPE sys.sqlprof_attr AS VARRAY(5000) of VARCHAR2(500);
REM
SET TERM ON ECHO OFF;
PRO
PRO Parameter 1:
PRO SQL_ID (required)
PRO
DEF sql_id = '&1';
PRO
WITH
p AS (
SELECT plan_hash_valueFROM gv$sql_planWHERE sql_id = TRIM('&&sql_id.')AND other_xml IS NOT NULLUNION
SELECT plan_hash_valueFROM dba_hist_sql_planWHERE sql_id = TRIM('&&sql_id.')AND other_xml IS NOT NULL ),
m AS (
SELECT plan_hash_value,SUM(elapsed_time)/SUM(executions) avg_et_secsFROM gv$sqlWHERE sql_id = TRIM('&&sql_id.')AND executions > 0GROUP BYplan_hash_value ),
a AS (
SELECT plan_hash_value,SUM(elapsed_time_total)/SUM(executions_total) avg_et_secsFROM dba_hist_sqlstatWHERE sql_id = TRIM('&&sql_id.')AND executions_total > 0GROUP BYplan_hash_value )
SELECT p.plan_hash_value,ROUND(NVL(m.avg_et_secs, a.avg_et_secs)/1e6, 3) avg_et_secsFROM p, m, aWHERE p.plan_hash_value = m.plan_hash_value(+)AND p.plan_hash_value = a.plan_hash_value(+)ORDER BYavg_et_secs NULLS LAST;
PRO
PRO Parameter 2:
PRO PLAN_HASH_VALUE (required)
PRO
DEF plan_hash_value = '&2';
PRO
PRO Values passed to coe_xfr_sql_profile:
PRO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PRO SQL_ID         : "&&sql_id."
PRO PLAN_HASH_VALUE: "&&plan_hash_value."
PRO
SET TERM OFF ECHO ON;
WHENEVER SQLERROR EXIT SQL.SQLCODE;-- trim parameters
COL sql_id NEW_V sql_id FOR A30;
COL plan_hash_value NEW_V plan_hash_value FOR A30;
SELECT TRIM('&&sql_id.') sql_id, TRIM('&&plan_hash_value.') plan_hash_value FROM DUAL;VAR sql_text CLOB;
VAR sql_text2 CLOB;
VAR other_xml CLOB;
EXEC :sql_text := NULL;
EXEC :sql_text2 := NULL;
EXEC :other_xml := NULL;-- get sql_text from memory
DECLAREl_sql_text VARCHAR2(32767);
BEGIN -- 10g see bug 5017909FOR i IN (SELECT DISTINCT piece, sql_textFROM gv$sqltext_with_newlinesWHERE sql_id = TRIM('&&sql_id.')ORDER BY 1, 2)LOOPIF :sql_text IS NULL THENDBMS_LOB.CREATETEMPORARY(:sql_text, TRUE);DBMS_LOB.OPEN(:sql_text, DBMS_LOB.LOB_READWRITE);END IF;-- removes NUL charactersl_sql_text := REPLACE(i.sql_text, CHR(00), ' ');-- adds a NUL character at the end of each lineDBMS_LOB.WRITEAPPEND(:sql_text, LENGTH(l_sql_text) + 1, l_sql_text||CHR(00));END LOOP;-- if found in memory then sql_text is not nullIF :sql_text IS NOT NULL THENDBMS_LOB.CLOSE(:sql_text);END IF;
EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('getting sql_text from memory: '||SQLERRM);:sql_text := NULL;
END;
/SELECT :sql_text FROM DUAL;-- get sql_text from awr
DECLAREl_sql_text VARCHAR2(32767);l_clob_size NUMBER;l_offset NUMBER;
BEGINIF :sql_text IS NULL OR NVL(DBMS_LOB.GETLENGTH(:sql_text), 0) = 0 THENSELECT sql_textINTO :sql_text2FROM dba_hist_sqltextWHERE sql_id = TRIM('&&sql_id.')AND sql_text IS NOT NULLAND ROWNUM = 1;END IF;-- if found in awr then sql_text2 is not nullIF :sql_text2 IS NOT NULL THENl_clob_size := NVL(DBMS_LOB.GETLENGTH(:sql_text2), 0);l_offset := 1;DBMS_LOB.CREATETEMPORARY(:sql_text, TRUE);DBMS_LOB.OPEN(:sql_text, DBMS_LOB.LOB_READWRITE);-- store in clob as 64 character pieces plus a NUL character at the end of each pieceWHILE l_offset < l_clob_sizeLOOPIF l_clob_size - l_offset > 64 THENl_sql_text := REPLACE(DBMS_LOB.SUBSTR(:sql_text2, 64, l_offset), CHR(00), ' ');ELSE -- last piecel_sql_text := REPLACE(DBMS_LOB.SUBSTR(:sql_text2, l_clob_size - l_offset + 1, l_offset), CHR(00), ' ');END IF;DBMS_LOB.WRITEAPPEND(:sql_text, LENGTH(l_sql_text) + 1, l_sql_text||CHR(00));l_offset := l_offset + 64;END LOOP;DBMS_LOB.CLOSE(:sql_text);END IF;
EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('getting sql_text from awr: '||SQLERRM);:sql_text := NULL;
END;
/SELECT :sql_text2 FROM DUAL;
SELECT :sql_text FROM DUAL;-- validate sql_text
SET TERM ON;
BEGINIF :sql_text IS NULL THENRAISE_APPLICATION_ERROR(-20100, 'SQL_TEXT for SQL_ID &&sql_id. was not found in memory (gv$sqltext_with_newlines) or AWR (dba_hist_sqltext).');END IF;
END;
/
SET TERM OFF;-- get other_xml from memory
BEGINFOR i IN (SELECT other_xmlFROM gv$sql_planWHERE sql_id = TRIM('&&sql_id.')AND plan_hash_value = TO_NUMBER(TRIM('&&plan_hash_value.'))AND other_xml IS NOT NULLORDER BYchild_number, id)LOOP:other_xml := i.other_xml;EXIT; -- 1stEND LOOP;
EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('getting other_xml from memory: '||SQLERRM);:other_xml := NULL;
END;
/-- get other_xml from awr
BEGINIF :other_xml IS NULL OR NVL(DBMS_LOB.GETLENGTH(:other_xml), 0) = 0 THENFOR i IN (SELECT other_xmlFROM dba_hist_sql_planWHERE sql_id = TRIM('&&sql_id.')AND plan_hash_value = TO_NUMBER(TRIM('&&plan_hash_value.'))AND other_xml IS NOT NULLORDER BYid)LOOP:other_xml := i.other_xml;EXIT; -- 1stEND LOOP;END IF;
EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('getting other_xml from awr: '||SQLERRM);:other_xml := NULL;
END;
/-- get other_xml from memory from modified SQL
BEGINIF :other_xml IS NULL OR NVL(DBMS_LOB.GETLENGTH(:other_xml), 0) = 0 THENFOR i IN (SELECT other_xmlFROM gv$sql_planWHERE plan_hash_value = TO_NUMBER(TRIM('&&plan_hash_value.'))AND other_xml IS NOT NULLORDER BYchild_number, id)LOOP:other_xml := i.other_xml;EXIT; -- 1stEND LOOP;END IF;
EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('getting other_xml from memory: '||SQLERRM);:other_xml := NULL;
END;
/-- get other_xml from awr from modified SQL
BEGINIF :other_xml IS NULL OR NVL(DBMS_LOB.GETLENGTH(:other_xml), 0) = 0 THENFOR i IN (SELECT other_xmlFROM dba_hist_sql_planWHERE plan_hash_value = TO_NUMBER(TRIM('&&plan_hash_value.'))AND other_xml IS NOT NULLORDER BYid)LOOP:other_xml := i.other_xml;EXIT; -- 1stEND LOOP;END IF;
EXCEPTIONWHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('getting other_xml from awr: '||SQLERRM);:other_xml := NULL;
END;
/SELECT :other_xml FROM DUAL;-- validate other_xml
SET TERM ON;
BEGINIF :other_xml IS NULL THENRAISE_APPLICATION_ERROR(-20101, 'PLAN for SQL_ID &&sql_id. and PHV &&plan_hash_value. was not found in memory (gv$sql_plan) or AWR (dba_hist_sql_plan).');END IF;
END;
/
SET TERM OFF;-- generates script that creates sql profile in target system:
SET ECHO OFF;
PRO coe_xfr_sql_profile_&&sql_id._&&plan_hash_value..sql.
SET FEED OFF LIN 666 TRIMS ON TI OFF TIMI OFF SERVEROUT ON SIZE 1000000 FOR WOR;
SET SERVEROUT ON SIZE UNL FOR WOR;
SPO OFF;
SPO coe_xfr_sql_profile_&&sql_id._&&plan_hash_value..sql;
DECLAREl_pos NUMBER;l_clob_size NUMBER;l_offset NUMBER;l_sql_text VARCHAR2(32767);l_len NUMBER;l_hint VARCHAR2(32767);
BEGINDBMS_OUTPUT.PUT_LINE('SPO coe_xfr_sql_profile_&&sql_id._&&plan_hash_value..log;');DBMS_OUTPUT.PUT_LINE('SET ECHO ON TERM ON LIN 2000 TRIMS ON NUMF 99999999999999999999;');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('REM $Header: 215187.1 coe_xfr_sql_profile_&&sql_id._&&plan_hash_value..sql 11.4.4.4 '||TO_CHAR(SYSDATE, 'YYYY/MM/DD')||' carlos.sierra $');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('REM Copyright (c) 2000-2012, Oracle Corporation. All rights reserved.');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('REM AUTHOR');DBMS_OUTPUT.PUT_LINE('REM   carlos.sierra@oracle.com');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('REM SCRIPT');DBMS_OUTPUT.PUT_LINE('REM   coe_xfr_sql_profile_&&sql_id._&&plan_hash_value..sql');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('REM DESCRIPTION');DBMS_OUTPUT.PUT_LINE('REM   This script is generated by coe_xfr_sql_profile.sql');DBMS_OUTPUT.PUT_LINE('REM   It contains the SQL*Plus commands to create a custom');DBMS_OUTPUT.PUT_LINE('REM   SQL Profile for SQL_ID &&sql_id. based on plan hash');DBMS_OUTPUT.PUT_LINE('REM   value &&plan_hash_value..');DBMS_OUTPUT.PUT_LINE('REM   The custom SQL Profile to be created by this script');DBMS_OUTPUT.PUT_LINE('REM   will affect plans for SQL commands with signature');DBMS_OUTPUT.PUT_LINE('REM   matching the one for SQL Text below.');DBMS_OUTPUT.PUT_LINE('REM   Review SQL Text and adjust accordingly.');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('REM PARAMETERS');DBMS_OUTPUT.PUT_LINE('REM   None.');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('REM EXAMPLE');DBMS_OUTPUT.PUT_LINE('REM   SQL> START coe_xfr_sql_profile_&&sql_id._&&plan_hash_value..sql;');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('REM NOTES');DBMS_OUTPUT.PUT_LINE('REM   1. Should be run as SYSTEM or SYSDBA.');DBMS_OUTPUT.PUT_LINE('REM   2. User must have CREATE ANY SQL PROFILE privilege.');DBMS_OUTPUT.PUT_LINE('REM   3. SOURCE and TARGET systems can be the same or similar.');DBMS_OUTPUT.PUT_LINE('REM   4. To drop this custom SQL Profile after it has been created:');DBMS_OUTPUT.PUT_LINE('REM      EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE(''coe_&&sql_id._&&plan_hash_value.'');');DBMS_OUTPUT.PUT_LINE('REM   5. Be aware that using DBMS_SQLTUNE requires a license');DBMS_OUTPUT.PUT_LINE('REM      for the Oracle Tuning Pack.');DBMS_OUTPUT.PUT_LINE('REM   6. If you modified a SQL putting Hints in order to produce a desired');DBMS_OUTPUT.PUT_LINE('REM      Plan, you can remove the artifical Hints from SQL Text pieces below.');DBMS_OUTPUT.PUT_LINE('REM      By doing so you can create a custom SQL Profile for the original');DBMS_OUTPUT.PUT_LINE('REM      SQL but with the Plan captured from the modified SQL (with Hints).');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('WHENEVER SQLERROR EXIT SQL.SQLCODE;');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('VAR signature NUMBER;');DBMS_OUTPUT.PUT_LINE('VAR signaturef NUMBER;');DBMS_OUTPUT.PUT_LINE('REM');DBMS_OUTPUT.PUT_LINE('DECLARE');DBMS_OUTPUT.PUT_LINE('sql_txt CLOB;');DBMS_OUTPUT.PUT_LINE('h       SYS.SQLPROF_ATTR;');DBMS_OUTPUT.PUT_LINE('PROCEDURE wa (p_line IN VARCHAR2) IS');DBMS_OUTPUT.PUT_LINE('BEGIN');DBMS_OUTPUT.PUT_LINE('DBMS_LOB.WRITEAPPEND(sql_txt, LENGTH(p_line), p_line);');DBMS_OUTPUT.PUT_LINE('END wa;');DBMS_OUTPUT.PUT_LINE('BEGIN');DBMS_OUTPUT.PUT_LINE('DBMS_LOB.CREATETEMPORARY(sql_txt, TRUE);');DBMS_OUTPUT.PUT_LINE('DBMS_LOB.OPEN(sql_txt, DBMS_LOB.LOB_READWRITE);');DBMS_OUTPUT.PUT_LINE('-- SQL Text pieces below do not have to be of same length.');DBMS_OUTPUT.PUT_LINE('-- So if you edit SQL Text (i.e. removing temporary Hints),');DBMS_OUTPUT.PUT_LINE('-- there is no need to edit or re-align unmodified pieces.');l_clob_size := NVL(DBMS_LOB.GETLENGTH(:sql_text), 0);l_offset := 1;WHILE l_offset < l_clob_sizeLOOPl_pos := DBMS_LOB.INSTR(:sql_text, CHR(00), l_offset);IF l_pos > 0 THENl_len := l_pos - l_offset;ELSE -- last piecel_len := l_clob_size - l_pos + 1;END IF;l_sql_text := DBMS_LOB.SUBSTR(:sql_text, l_len, l_offset);/* cannot do such 3 replacement since a line could end with a comment using "--"l_sql_text := REPLACE(l_sql_text, CHR(10), ' '); -- replace LF with SPl_sql_text := REPLACE(l_sql_text, CHR(13), ' '); -- replace CR with SPl_sql_text := REPLACE(l_sql_text, CHR(09), ' '); -- replace TAB with SP*/l_offset := l_offset + l_len + 1;IF l_len > 0 THENIF INSTR(l_sql_text, '''[') + INSTR(l_sql_text, ']''') = 0 THENl_sql_text := '['||l_sql_text||']';ELSIF INSTR(l_sql_text, '''{') + INSTR(l_sql_text, '}''') = 0 THENl_sql_text := '{'||l_sql_text||'}';ELSIF INSTR(l_sql_text, '''<') + INSTR(l_sql_text, '>''') = 0 THENl_sql_text := '<'||l_sql_text||'>';ELSIF INSTR(l_sql_text, '''(') + INSTR(l_sql_text, ')''') = 0 THENl_sql_text := '('||l_sql_text||')';ELSIF INSTR(l_sql_text, '''"') + INSTR(l_sql_text, '"''') = 0 THENl_sql_text := '"'||l_sql_text||'"';ELSIF INSTR(l_sql_text, '''|') + INSTR(l_sql_text, '|''') = 0 THENl_sql_text := '|'||l_sql_text||'|';ELSIF INSTR(l_sql_text, '''~') + INSTR(l_sql_text, '~''') = 0 THENl_sql_text := '~'||l_sql_text||'~';ELSIF INSTR(l_sql_text, '''^') + INSTR(l_sql_text, '^''') = 0 THENl_sql_text := '^'||l_sql_text||'^';ELSIF INSTR(l_sql_text, '''@') + INSTR(l_sql_text, '@''') = 0 THENl_sql_text := '@'||l_sql_text||'@';ELSIF INSTR(l_sql_text, '''#') + INSTR(l_sql_text, '#''') = 0 THENl_sql_text := '#'||l_sql_text||'#';ELSIF INSTR(l_sql_text, '''%') + INSTR(l_sql_text, '%''') = 0 THENl_sql_text := '%'||l_sql_text||'%';ELSIF INSTR(l_sql_text, '''$') + INSTR(l_sql_text, '$''') = 0 THENl_sql_text := '$'||l_sql_text||'$';ELSEl_sql_text := CHR(96)||l_sql_text||CHR(96);END IF;DBMS_OUTPUT.PUT_LINE('wa(q'''||l_sql_text||''');');END IF;END LOOP;DBMS_OUTPUT.PUT_LINE('DBMS_LOB.CLOSE(sql_txt);');DBMS_OUTPUT.PUT_LINE('h := SYS.SQLPROF_ATTR(');DBMS_OUTPUT.PUT_LINE('q''[BEGIN_OUTLINE_DATA]'',');FOR i IN (SELECT /*+ opt_param('parallel_execution_enabled', 'false') */SUBSTR(EXTRACTVALUE(VALUE(d), '/hint'), 1, 4000) hintFROM TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE(:other_xml), '/*/outline_data/hint'))) d)LOOPl_hint := i.hint;WHILE NVL(LENGTH(l_hint), 0) > 0LOOPIF LENGTH(l_hint) <= 500 THENDBMS_OUTPUT.PUT_LINE('q''['||l_hint||']'',');l_hint := NULL;ELSEl_pos := INSTR(SUBSTR(l_hint, 1, 500), ' ', -1);DBMS_OUTPUT.PUT_LINE('q''['||SUBSTR(l_hint, 1, l_pos)||']'',');l_hint := '   '||SUBSTR(l_hint, l_pos);END IF;END LOOP;END LOOP;DBMS_OUTPUT.PUT_LINE('q''[END_OUTLINE_DATA]'');');DBMS_OUTPUT.PUT_LINE(':signature := DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt);');DBMS_OUTPUT.PUT_LINE(':signaturef := DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt, TRUE);');DBMS_OUTPUT.PUT_LINE('DBMS_SQLTUNE.IMPORT_SQL_PROFILE (');DBMS_OUTPUT.PUT_LINE('sql_text    => sql_txt,');DBMS_OUTPUT.PUT_LINE('profile     => h,');DBMS_OUTPUT.PUT_LINE('name        => ''coe_&&sql_id._&&plan_hash_value.'',');DBMS_OUTPUT.PUT_LINE('description => ''coe &&sql_id. &&plan_hash_value. ''||:signature||'' ''||:signaturef||'''',');DBMS_OUTPUT.PUT_LINE('category    => ''DEFAULT'',');DBMS_OUTPUT.PUT_LINE('validate    => TRUE,');DBMS_OUTPUT.PUT_LINE('replace     => TRUE,');DBMS_OUTPUT.PUT_LINE('force_match => FALSE /* TRUE:FORCE (match even when different literals in SQL). FALSE:EXACT (similar to CURSOR_SHARING) */ );');DBMS_OUTPUT.PUT_LINE('DBMS_LOB.FREETEMPORARY(sql_txt);');DBMS_OUTPUT.PUT_LINE('END;');DBMS_OUTPUT.PUT_LINE('/');DBMS_OUTPUT.PUT_LINE('WHENEVER SQLERROR CONTINUE');DBMS_OUTPUT.PUT_LINE('SET ECHO OFF;');DBMS_OUTPUT.PUT_LINE('PRINT signature');DBMS_OUTPUT.PUT_LINE('PRINT signaturef');DBMS_OUTPUT.PUT_LINE('PRO');DBMS_OUTPUT.PUT_LINE('PRO ... manual custom SQL Profile has been created');DBMS_OUTPUT.PUT_LINE('PRO');DBMS_OUTPUT.PUT_LINE('SET TERM ON ECHO OFF LIN 80 TRIMS OFF NUMF "";');DBMS_OUTPUT.PUT_LINE('SPO OFF;');DBMS_OUTPUT.PUT_LINE('PRO');DBMS_OUTPUT.PUT_LINE('PRO COE_XFR_SQL_PROFILE_&&sql_id._&&plan_hash_value. completed');
END;
/
SPO OFF;
SET DEF ON TERM ON ECHO OFF FEED 6 VER ON HEA ON LIN 80 PAGES 14 LONG 80 LONGC 80 TRIMS OFF TI OFF TIMI OFF SERVEROUT OFF NUMF "" SQLP SQL>;
SET SERVEROUT OFF;
PRO
PRO Execute coe_xfr_sql_profile_&&sql_id._&&plan_hash_value..sql
PRO on TARGET system in order to create a custom SQL Profile
PRO with plan &&plan_hash_value linked to adjusted sql_text.
PRO
UNDEFINE 1 2 sql_id plan_hash_value
CL COL
PRO
PRO COE_XFR_SQL_PROFILE completed.
SQL> @coe_xfr_sql_profile.sqlParameter 1:
SQL_ID (required)?? 1 μ?μ:  0n82d9qnjxhxvPLAN_HASH_VALUE AVG_ET_SECS
--------------- -----------1483576328        .9631285018022     963.461Parameter 2:
PLAN_HASH_VALUE (required)输入 2 的值:  1483576328Values passed to coe_xfr_sql_profile:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQL_ID	       : "0n82d9qnjxhxv"
PLAN_HASH_VALUE: "1483576328"SQL>BEGIN2    IF :sql_text IS NULL THEN3  	 RAISE_APPLICATION_ERROR(-20100, 'SQL_TEXT for SQL_ID &&sql_id. was not found in memory (gv$sqltext_with_newlines) or AWR (dba_hist_sqltext).');4    END IF;5  END;6  /
SQL>SET TERM OFF;
SQL>BEGIN2    IF :other_xml IS NULL THEN3  	 RAISE_APPLICATION_ERROR(-20101, 'PLAN for SQL_ID &&sql_id. and PHV &&plan_hash_value. was not found in memory (gv$sql_plan) or AWR (dba_hist_sql_plan).');4    END IF;5  END;6  /
SQL>SET TERM OFF;
4之后再次查看表当前统计信息,进行验证
select owner, table_name, num_rows, blocks, avg_row_len, partitioned, to_char(last_analyzed, 'YYYY-MM-DD HH24:MI:SS')from dba_tableswhere owner ='用户名’and table_name in ('表名');

3.2 问题分析总结

  • 综合上述分析,我们可以看到:本次问题出现的原因一个是Oracle周末自动收集统计信息的时间正好在表清数之后,发生巧合导致执行计划发生改变,还有一点是业务对表进行大量的增删改操作后发现前后数据量没有什么区别,所以认为数据量变化不大对问题处理造成误导,在大批量量的增删改操作后应对表进行统计信息的收集工作。

4. 处理/优化建议

  1. 除了该表外,自动的收集统计信息任务是对全数据库进行的,还需要查看该库下其他表是否也存在执行计划改变的情况。
  2. 加强协作,和业务人员进行有效的交流沟通,明确跑批都进行了什么操作,并且建议业务人员在之后对表进行大量的增删改操作后及时收集统计信息,更新执行计划。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/828504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS —— 仿 XPermission 鸿蒙权限申请工具类

仿 XPermission 写一个简单的鸿蒙权限申请工具类。 import { abilityAccessCtrl, bundleManager, Context, Permissions } from kit.AbilityKit import { ArrayList } from kit.ArkTSexport class PermissionUtil {private static readonly sUtil: PermissionUtil new Permis…

CUDA的应用场景

CUDA的应用场景随着技术的发展不断扩展&#xff0c;其核心优势在于能够显著提高并行计算任务的处理速度&#xff0c;这对于任何需要处理大量数据和执行复杂计算的领域都是极其有价值的。CUDA开发的应用场景非常广泛&#xff0c;主要得益于其强大的并行计算能力&#xff0c;以下…

buuctf——[CISCN2019 华北赛区 Day2 Web1]Hack World

buuctf——[CISCN2019 华北赛区 Day2 Web1]Hack World 1.根据提示&#xff0c;说明flag在表里 2.那就猜测存在sql注入&#xff0c;反手测试一波id1 3.尝试使用1--进行注释 4.直接丢进salmap里吧&#xff0c;不出意外多半是跑不出来 5.直接放入fuzz里进行测试 6.发现当我…

iOS - 多线程-GCD

文章目录 iOS - 多线程-GCD1. 常见多线程方案2. GCD2.1 GCD的常见函数GCD中有2个用来执行任务的函数 2.2 GCD的队列2.2.1 GCD的队列可以分为2大类型 2.3 容易混淆的术语2.4.1 有4个术语比较容易混淆&#xff1a;同步、异步、并发、串行 2.4 各种队列的执行效果 3. 死锁3.1 死锁…

Composer初次接触

php一直都是简单处理一下单片机的后台服务&#xff0c;没什么深入研究 今天安装一个 php composer.phar require qiniu/php-sdkComposer完全不懂&#xff0c;照着一试&#xff0c;就报错了 - topthink/think-installer v1.0.12 requires composer-plugin-api ^1.0 -> found…

ThreeJs模拟工厂生产过程三

上节课绘制了车间模型&#xff0c;但是车间里只有一条产线&#xff0c;这节把产线多铺设几条&#xff0c;放满整个车间&#xff0c;但是随着放满车间吗&#xff0c;也就意味着要创建更多的模型&#xff0c;而更多的模型会导致浏览器卡顿&#xff0c;所以这个节讲如何做模型合并…

linux 下如何确定驱动是否已经正常加载了

1.系统日志 嵌入式系统&#xff0c;使用dmesg 指令&#xff0c;如&#xff1a; # dmesg | grep usb [ 0.253890] usbcore: registered new interface driver usbfs [ 0.253951] usbcore: registered new interface driver hub [ 0.254026] usbcore: registered new …

Python | Leetcode Python题解之第48题旋转图像

题目&#xff1a; 题解&#xff1a; class Solution:def rotate(self, matrix: List[List[int]]) -> None:n len(matrix)# 水平翻转for i in range(n // 2):for j in range(n):matrix[i][j], matrix[n - i - 1][j] matrix[n - i - 1][j], matrix[i][j]# 主对角线翻转for …

Python400集 视频教程,手把手带你零基础手写神经网络!!

嗨喽&#xff0c;大家好&#xff0c;今天又要给大家整一波福利了&#xff01; 学习编程&#xff0c;最忌讳就是今天一个教程&#xff0c;明天一个教程&#xff0c;频繁更换教程&#xff0c;增加自己的学习成本&#xff0c;对于新手小白会是一件严重打击自信心的事情。所以今天…

【嵌入式经验积累】锂电池与充电

文章目录 警告锂电池的基本参数锂电池的材料锂电池的充电阶段预充电恒流充电恒压充电复充电锂电池的充电温度范围锂电池的放电温度范围锂电池充电芯片警告 以下警告是由国内一家锂电池厂商告知的: 锂电池只有过充和过热才会爆炸(非外力)。所以一定要保证锂电池在充电过程中不…

Jmeter实现参数化的四种方法

目录 一、CSV Data Set Config/CSV数据文件设置 二、函数助手 1、Random函数 2、RandomString随机字符串 3、CSVRead 4、time 5、UUID 三、计数器&#xff08;Counter&#xff09; 参数化&#xff1a;自动化测试脚本的一种常用技巧&#xff0c;事先准备好数据&#xff…

四川尚熠电子商务有限公司抖音电商新势力的崛起

在当下这个数字化高速发展的时代&#xff0c;电子商务已经成为推动经济增长的重要引擎之一。四川尚熠电子商务有限公司&#xff0c;作为一股新兴的电商力量&#xff0c;专注于抖音电商服务&#xff0c;凭借其独特的市场洞察力和创新精神&#xff0c;正逐步在激烈的市场竞争中崭…

portaudio 怎么调用获取输出流

PortAudio是一个跨平台的音频I/O库&#xff0c;它允许你访问计算机的音频硬件进行录音和播放。要使用PortAudio获取输出流&#xff08;播放流&#xff09;&#xff0c;你需要遵循以下步骤&#xff1a; 官方下载地址&#xff1a;PortAudio - an Open-Source Cross-Platform Audi…

安全评估报告 项目安全风险评估报告 信息安全评估报告

一、安全评估报告的意义 安全评估报告是对特定环境、设施或系统安全性进行全 面分析、评估和预测的重要工具。它通过对潜在风险的识别、分析和评价&#xff0c;帮助决策者了解当前安全形势&#xff0c;制定科学的安全策略&#xff0c;从而有 效预防和减少安全事故的发生。安全…

Linux 系统IO函数之open函数

open函数 要点&#xff1a; int open(const char *pathname, int flags); perror函数 close函数 控制台输入&#xff1a; man 2 open2 表示第二章&#xff08;Linux系统IO函数位于第二章&#xff09;&#xff0c;第三章是标准C库的一些函数部分输出&#xff1a; 1、open函数返…

【ruoyi-vue】axios的封装理解和基本使用

axios的配置 ruoyi的前端对axios进行了封装&#xff0c;让我们发get请求或者是post请求更加方便了。 ruoyi对axios的封装在下面文件中&#xff1a;打开文件&#xff0c;可以看到它有三个显眼的方法&#xff0c;分别是request拦截器、response拦截器和通用下载方法。ruoYi接口地…

RK3588构建ubuntu22.04根文件系统

前言 RK系列的平台提供了buildroot和debian的系统&#xff0c;使用脚本可以直接构建出来&#xff0c;但是没有提供ubuntu的系统&#xff0c;很多厂商只提供一个rootfs.img的固件包&#xff0c;没有将方法开源出来。本文实现了从ubuntu官网开始构建一个ubuntu22.04根文件系统。…

程序员副业项目快速验证最小MVP

最小可行产品和产品市场契合 上次我们讲解了如何通过商业模式画布来规划商业逻辑&#xff0c;但是「所有的战略和规划都是基于假设」&#xff0c;只有经过验证的认知才是可靠、可信的。因此&#xff0c;接下来我们需要通过实验的方式来验证这些假设。 通常&#xff0c;我们会采…

【信息收集】端口扫描masscan负载均衡识别lbd

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、什么是masscan masscan在kali系统上是自带的端口扫描…

数据结构与算法学习笔记一---线性表的实现(C语言)

目录 2.线性表的实现 1.线性表的顺序存储表示 1.定义 2.初始化 3.判断是否为空表 4.求表长 5.查找 6.查询直接前驱节点 7.查询直接后继节点 8. 插入顺序表插入 9.删除节点 10.遍历顺序表 11.完整代码 2.线性表的链式存储表示 1.定义 2.初始化 3.判断是否为空表…