Statistics gathering and SQL Tuning Advisor

Posted feiyun8616的作坊 (半个程序员and dba)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Statistics gathering and SQL Tuning Advisor相关的知识,希望对你有一定的参考价值。

 

1. https://www.pythian.com/blog/statistics-gathering-and-sql-tuning-advisor/

Our monitoring software found a long running job on one of our client’s databases. The job was an Oracle’s auto task running statistics gathering for more than 3 hours. I was curious to know why it took so long and used a query to ASH to find out the most common SQL during the job run based on the module name. Results were surprising to me: top SQL was coming with SQL Tuning Advisor comment.

Here is the SQL I used:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SQL> select s.sql_id, t.sql_text, s.cnt
  from
  3    (select *
  4     from
  5      (
  6        select sql_id, count(*) cnt
  7        from v$active_session_history
  8        where action like ‘ORA$AT_OS_OPT_SY%‘
  9        group by sql_id
 10        order by count(*) desc
 11      )
 12     where rownum <= 5
 13    ) s,
 14    dba_hist_sqltext t
 15  where s.sql_id = t.sql_id;
 
SQL_ID        SQL_TEXT                                                                                CNT
------------- -------------------------------------------------------------------------------- ----------
020t65s3ah2pq select substrb(dump(val,16,0,32),1,120) ep, cnt from (select /*+ no_expand_table        781
byug0cc5vn416 /* SQL Analyze(1) */ select /*+  full(t)    no_parallel(t) no_parallel_index(t)          43
bkvvr4azs1n6z /* SQL Analyze(1) */ select /*+  full(t)    no_parallel(t) no_parallel_index(t)          21
46sy4dfg3xbfn /* SQL Analyze(1) */ select /*+  full(t)    no_parallel(t) no_parallel_index(t)        1559

So most queries are coming with “SQL Analyze” comment right in the beginning of SQL which is running from DBMS_STATS call, which is confusing. After some bug search I have found a MOS Doc ID 1480132.1 which includes a PL/SQL stack trace from a DBMS_STATS procedure call, and it is going up to DBMS_SQLTUNE_INTERNAL, which means DBMS_STATS has a call to the SQL Tuning package; very odd:

1
2
3
4
5
6
7
8
SQL> select * from dba_dependencies where name = ‘DBMS_STATS_INTERNAL‘ and referenced_name = ‘DBMS_SQLTUNE_INTERNAL‘;
 
OWNER                          NAME                           TYPE               REFERENCED_OWNER       REFERENCED_NAME
------------------------------ ------------------------------ ------------------ ------------------------------ ----------------------------------
REFERENCED_TYPE    REFERENCED_LINK_NAME                                                                                                     DEPE
------------------ -------------------------------------------------------------------------------------------------------------------------------
SYS                            DBMS_STATS_INTERNAL            PACKAGE BODY       SYS                    DBMS_SQLTUNE_INTERNAL
PACKAGE                                                                                                                                     HARD

Turns out, this call has nothing to do with the SQL Tuning. It is just a call to a procedure in this package, which happen to look like an SQL from SQL Tuning Advisor. I have traced a GATHER_TABLE_STATS call in a test database first with SQL trace and then with DBMS_HPROF and here is how the call tree looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
SELECT RPAD(‘ ‘, (level-1)*2, ‘ ‘) || fi.owner || ‘.‘ || fi.module AS name,
       fi.function,
       pci.subtree_elapsed_time,
       pci.function_elapsed_time,
       pci.calls
FROM   dbmshp_parent_child_info pci
       JOIN dbmshp_function_info fi ON pci.runid = fi.runid AND pci.childsymid = fi.symbolid
WHERE  pci.runid = 1
CONNECT BY PRIOR childsymid = parentsymid
  START WITH pci.parentsymid = 27;
NAME                                     FUNCTION                       SUBTREE_ELAPSED_TIME FUNCTION_ELAPSED_TIME                CALLS
---------------------------------------- ------------------------------ -------------------- --------------------- --------------------
...
SYS.DBMS_STATS_INTERNAL                  GATHER_SQL_STATS                           21131962                 13023                    1
  SYS.DBMS_ADVISOR                       __pkg_init                                       88                    88                    1
  SYS.DBMS_SQLTUNE_INTERNAL              GATHER_SQL_STATS                           21118776                  9440                    1
    SYS.DBMS_SQLTUNE_INTERNAL            I_PROCESS_SQL                              21107094              21104225                    1
      SYS.DBMS_LOB                       GETLENGTH                                        37                    37                    1
      SYS.DBMS_LOB                       INSTR                                            42                    42                    1
      SYS.DBMS_LOB                       __pkg_init                                       15                    15                    1
      SYS.DBMS_SQLTUNE_INTERNAL          I_VALIDATE_PROCESS_ACTION                        74                    39                    1
        SYS.DBMS_UTILITY                 COMMA_TO_TABLE                                   35                    35                    1
      SYS.DBMS_SQLTUNE_UTIL0             SQLTEXT_TO_SIGNATURE                            532                   532                    1
      SYS.DBMS_SQLTUNE_UTIL0             SQLTEXT_TO_SQLID                                351                   351                    1
      SYS.XMLTYPE                        XMLTYPE                                        1818                  1818                    1
    SYS.DBMS_SQLTUNE_UTIL0               SQLTEXT_TO_SQLID                                528                   528                    1
    SYS.DBMS_UTILITY                     COMMA_TO_TABLE                                   88                    88                    1
    SYS.DBMS_UTILITY                     __pkg_init                                       10                    10                    1
    SYS.SQLSET_ROW                       SQLSET_ROW                                       33                    33                    1
    SYS.XMLTYPE                          XMLTYPE                                        1583                  1583                    1
  SYS.DBMS_STATS_INTERNAL                DUMP_PQ_SESSTAT                                  73                    73                    1
  SYS.DBMS_STATS_INTERNAL                DUMP_QUERY                                        2                     2                    1
...

So there is a procedure DBMS_SQLTUNE_INTERNAL.GATHER_SQL_STATS which is being called by DBMS_STATS_INTERNAL, and this procedure actually runs a SQL like this:

1
/* SQL Analyze(0) */ select /*+  full(t)    no_parallel(t) no_parallel_index(t) dbms_stats cursor_sharing_exact use_weak_name_resl dynamic_sampling(0) no_monitoring no_substrb_pad  */to_char(count("ID")),to_char(substrb(dump(min("ID"),16,0,32),1,120)),to_char(substrb(dump(max("ID"),16,0,32),1,120)),to_char(count("X")),to_char(substrb(dump(min("X"),16,0,32),1,120)),to_char(substrb(dump(max("X"),16,0,32),1,120)),to_char(count("Y")),to_char(substrb(dump(min("Y"),16,0,32),1,120)),to_char(substrb(dump(max("Y"),16,0,32),1,120)),to_char(count("PAD")),to_char(substrb(dump(min("PAD"),16,0,32),1,120)),to_char(substrb(dump(max("PAD"),16,0,32),1,120)) from "TIM"."T1" /* NDV,NIL,NIL,NDV,NIL,NIL,NDV,NIL,NIL,NDV,NIL,NIL*/

Which is basically approximate NDV calculation. So, nothing to be afraid of, it’s just the way the code is organized: DBMS_STATS uses API of SQL Tuning framework when you are using DBMS_STATS.AUTO_SAMPLE_SIZE as the ESTIMATE_PERCENT (which is the default & recommended value in 11g+).

 

 

2.

http://blog.csdn.net/stevendbaguo/article/details/50856002

 接到现场数据库维护厂商发出的警告,有一条 insert语句执行了几千秒。

       开发排查,从select * from dba_source s where s.text like ‘%XXX%‘;查到是一个存储过程,于是找到存储过程,将其改名。

       但问题没有解决,隔天又收到警告。

       难道是存储过程改名有问题,我远程到现场看了下,并没有问题。再次查看数据库报告:

       SQL Module  是 DBMS_SCHEDULER,确定无疑是Oracle JOB调用,奇怪的是SQL语句有  /* SQL Analyze(194, 1) */ 这样的提示。

       如果想定位到这条SQL,最好是找到这条SQL历史执行的session,希望找到蛛丝马迹。

       select * from dba_hist_active_sess_history s where s.sql_id=‘29yrhxqdk2d1q‘; 

       TOP_LEVEL_SQL_ID 为5zruc4v6y32f9:说明是sql_id为5zruc4v6y32f9的调用的这条sql 

       MODULE:DBMS_SCHEDULER

       PLSQL_ENTRY_OBJECT_ID:9013

       根据上面的信息再进行查询:

9013;--结果是owner=sys  object_name=dbms_sqltune

5zruc4v6y32f9

DECLARE
  job                 BINARY_INTEGER := :job;
  next_date           TIMESTAMP WITH TIME ZONE := :mydate;
  broken              BOOLEAN := FALSE;
  job_name            VARCHAR2(30) := :job_name;
  job_subname         VARCHAR2(30) := :job_subname;
  job_owner           VARCHAR2(30) := :job_owner;
  job_start           TIMESTAMP WITH TIME ZONE := :job_start;
  job_scheduled_start TIMESTAMP WITH TIME ZONE := :job_scheduled_start;
  window_start        TIMESTAMP WITH TIME ZONE := :window_start;
  window_end          TIMESTAMP WITH TIME ZONE := :window_end;
  chain_id            VARCHAR2(14) := :chainid;
  credential_owner    varchar2(30) := :credown;
  credential_name     varchar2(30) := :crednam;
  destination_owner   varchar2(30) := :destown;
  destination_name    varchar2(30) := :destnam;
  job_dest_id         varchar2(14) := :jdestid;
  log_id              number := :log_id;
BEGIN
  DECLARE
    ename VARCHAR2(30);
  BEGIN
    ename := dbms_sqltune.execute_tuning_task(‘SYS_AUTO_SQL_TUNING_TASK‘);
  END;
  :mydate := next_date;
  IF broken THEN
    :b := 1;
  ELSE
    :b := 0;
  END IF;
END;

       这是数据库SQL优化的包,自己调用的,终于明白 /* SQL Analyze(194, 1) */的意思了,是标记这种优化包调用的。

 

3.

http://blog.itpub.net/23718752/viewspace-1252180/

 

在昨天晚上10点开始,数据库的性能开始下降,出现了一些j00开头的进程。
而且持续了比较长的时间,简单分析了一下,对应的进程执行的sql语句如下。

####### Process Information from OS level as below ########
oraccbs1 16184     1 23 22:00 ?        00:03:09 ora_j000_PETCUS1
oraccbs1 20829 12754  0 22:14 pts/12   00:00:00 ksh showpid.sh 16184
##############################################

       SID    SERIAL# USERNAME        OSUSER          MACHINE              PROCESS         TERMINAL        TYPE       LOGIN_TIME
---------- ---------- --------------- --------------- -------------------- --------------- --------------- ---------- -------------------
      1139       1071 SYS             oraccbs1        xxxxxx               16184           UNKNOWN         USER       2014-08-14 22:00:43

.

SQL_ID                         SQL_TEXT
------------------------------ ------------------------------------------------------------
6fwshkjydz9ph                  /* SQL Analyze(1) */ select /*+  full(t)    no_parallel(t) n
                               o_parallel_index(t) dbms_stats cursor_sharing_exact use_weak
                               _name_resl dynamic_sampling(0) no_monitoring no_substrb_pad
                                */to_char(count("PERIOD_KEY")),to_char(substrb(dump(min("PE
                               RIOD_KEY"),16,0,32),1,120)),to_char(substrb(dump(max("PERIOD
                               _KEY"),16,0,32),1,120)),to_char(count("PARTITION_ID")),to_ch
                               ar(substrb(dump(min("PARTITION_ID"),16,0,32),1,120)),to_char
                               (substrb(dump(max("PARTITION_ID"),16,0,32),1,120)),to_char(c
                               ount("DEBIT_ID")),to_char(substrb(dump(min("DEBIT_ID"),16,0,
                               32),1,120)),to_char(substrb(dump(max("DEBIT_ID"),16,0,32),1,
                               120)),to_char(count("SYS_CREATION_DATE")),to_char(substrb(du
                               mp(min("SYS_CREATION_DATE"),16,0,32),1,120)),to_char(substrb
                               (dump(max("SYS_CREATION_DATE"),16,0,32),1,120)),to_char(coun
                               t("SYS_UPDATE_DATE")),to_char(substrb(dump(min("SYS_UPDATE_D
                               ATE"),16,0,32),1,120)),to_char(substrb(dump(max("SYS_UPDATE_
                               DATE"),16,0,32),1,120)),to_char(count("OPERATOR_ID")),to_cha
                               r(substrb(dump(min("OPERATOR_ID"),16,0,3

 

PREV_SQL_ID                    SQL_TEXT
------------------------------ ------------------------------------------------------------
fhzj09a7fnrnb                  SELECT DBTIMEZONE, LENGTH(DBTIMEZONE) FROM SYS.DUAL

 
看起来是在做一些后台的维护工作。在11g中引入了几个schedule job,简单查询,结果如下。可以看到在每天都设置了对应的window。
在10点开始做一些工作。以下是禁用以后的状态。

SQL> execute DBMS_AUTO_TASK_ADMIN.DISABLE;

PL/SQL procedure successfully completed.

SQL> select * from DBA_AUTOTASK_WINDOW_CLIENTS;

WINDOW_NAME                    WINDOW_NEXT_TIME                                                            WINDO AUTOTASK OPTIMIZE SEGMENT_ SQL_TUNE HEALTH_M
------------------------------ --------------------------------------------------------------------------- ----- -------- -------- -------- -------- --------
MONDAY_WINDOW                  18-AUG-14 10.00.00.000000 PM ASIA/PHNOM_PENH                                FALSE DISABLED ENABLED  ENABLED  ENABLED  DISABLED
TUESDAY_WINDOW                 19-AUG-14 10.00.00.000000 PM ASIA/PHNOM_PENH                                FALSE DISABLED ENABLED  ENABLED  ENABLED  DISABLED
WEDNESDAY_WINDOW               20-AUG-14 10.00.00.000000 PM ASIA/PHNOM_PENH                                FALSE DISABLED ENABLED  ENABLED  ENABLED  DISABLED
THURSDAY_WINDOW                14-AUG-14 10.00.00.000000 PM ASIA/PHNOM_PENH                                TRUE  DISABLED ENABLED  ENABLED  ENABLED  DISABLED
FRIDAY_WINDOW                  15-AUG-14 10.00.00.000000 PM ASIA/PHNOM_PENH                                FALSE DISABLED ENABLED  ENABLED  ENABLED  DISABLED
SATURDAY_WINDOW                16-AUG-14 06.00.00.000000 AM ASIA/PHNOM_PENH                                FALSE DISABLED ENABLED  ENABLED  ENABLED  DISABLED
SUNDAY_WINDOW                  17-AUG-14 06.00.00.000000 AM ASIA/PHNOM_PENH                                FALSE DISABLED ENABLED  ENABLED  ENABLED  DISABLED

7 rows selected.

其实3个主要的后台job可以选择关掉。

SQL> select client_name,status from DBA_AUTOTASK_CLIENT;


CLIENT_NAME                                                      STATUS
---------------------------------------------------------------- --------
auto optimizer stats collection                                  ENABLED
auto space advisor                                               ENABLED
sql tuning advisor                                               ENABLED

使用如下的pl/sql来禁用。

begin
DBMS_AUTO_TASK_ADMIN.DISABLE(client_name => ‘auto optimizer stats collection‘,
operation => NULL,
window_name => NULL);
end;
/


begin
DBMS_AUTO_TASK_ADMIN.DISABLE(client_name => ‘auto space advisor‘,
operation => NULL,
window_name => NULL);
end;
/

begin
DBMS_AUTO_TASK_ADMIN.DISABLE(client_name => ‘sql tuning advisor‘,
operation => NULL,
window_name => NULL);
end;
/

禁用以后,状态如下:

SQL> select client_name,status from DBA_AUTOTASK_CLIENT;

CLIENT_NAME                                                      STATUS
---------------------------------------------------------------- --------
auto optimizer stats collection                                  DISABLED
auto space advisor                                               DISABLED
sql tuning advisor                                               DISABLED

但是不会当时生效,需要过一段时间,所以需要提前禁用。




































































































以上是关于Statistics gathering and SQL Tuning Advisor的主要内容,如果未能解决你的问题,请参考以下文章

SQL调优指南笔记13:Gathering Optimizer Statistics

SQL调优指南笔记12:Configuring Options for Optimizer Statistics Gathering

SQL调优指南笔记12:Configuring Options for Optimizer Statistics Gathering

Nikita and Order Statistics

Statistics and Linear Algebra 4

Statistics and Linear Algebra 1