欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

示例演示直方图的重要性

程序员文章站 2022-05-24 11:17:37
...

1. 示例说明直方图的作用。 初始化数据 dexter@STARTREK select count(*) fromall_objects ; COUNT(*) ---------- 72642 dexter@STARTREK create table tuning4_tabnologging as select * from all_objects ; Table created. dexter@STARTREK select count(*

1. 示例说明直方图的作用。

初始化数据

dexter@STARTREK> select count(*) fromall_objects ;

COUNT(*)

----------

72642

dexter@STARTREK> create table tuning4_tabnologging as select * from all_objects ;

Table created.

dexter@STARTREK> select count(*) fromall_objects ;

COUNT(*)

----------

72643

dexter@STARTREK> create indexidx_tuning4_tab_owner on tuning4_tab (owner) ;

Index created.

dexter@STARTREK> @gather_tab

Enter value for tbname: tuning4_tab

PL/SQL procedure successfully completed.

在这里碰到了一个小问题,因为数据的倾斜比较严重,而且oracle数据库在执行gather_table_stats的时候没有收集owner列的统计信息,这里优化器选择了错误的执行计划。下面记录了完整的处理过程。

出现错误的执行计划

dexter@STARTREK> select* from tuning4_Tab where owner='SYS' or owner='PUBLIC' ;

59253 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 989038285

------------------------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

------------------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 4687 | 443K| 139 (0)| 00:00:01 |

| 1 | INLIST ITERATOR | | | | | |

| 2 | TABLE ACCESS BY INDEX ROWID| TUNING4_TAB | 4687 | 443K| 139 (0)| 00:00:01 |

|* 3 | INDEX RANGE SCAN |IDX_TUNING4_TAB_OWNER | 4687 | | 13 (0)| 00:00:01 |

------------------------------------------------------------------------------------------------------

Predicate Information(identified by operation id):

---------------------------------------------------

3 - access("OWNER"='PUBLIC' OR"OWNER"='SYS')

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

9581 consistent gets

0 physical reads

0 redo size

6805858 bytes sent via SQL*Net to client

43970 bytes received via SQL*Net from client

3952 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

59253 rows processed

下面的输出可以看到,其实使用全表扫描的效率要高于indexrange scan。

dexter@STARTREK> select /*+full(tuning4_tab)*/ *from tuning4_Tab where owner='SYS' or owner='PUBLIC' ;

59253 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 1641193091

---------------------------------------------------------------------------------

| Id |Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

---------------------------------------------------------------------------------

| 0 |SELECT STATEMENT | | 4687 | 443K| 290 (1)| 00:00:01 |

|* 1 | TABLE ACCESS FULL| TUNING4_TAB | 4687 | 443K| 290 (1)| 00:00:01 |

---------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 -filter("OWNER"='PUBLIC' OR "OWNER"='SYS')

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

4927 consistent gets

0 physical reads

0 redo size

3035580 bytes sent via SQL*Net toclient

43970 bytes received via SQL*Netfrom client

3952 SQL*Net roundtrips to/fromclient

0 sorts (memory)

0 sorts (disk)

59253 rows processed

dexter@STARTREK>

trace 一下

dexter@STARTREK> alter session settracefile_identifier=histogram ;

Session altered.

dexter@STARTREK> alter session set events '10053trace name context forever ,level 12';

Session altered.

dexter@STARTREK> select * from tuning4_Tab whereowner='SYS' or owner='PUBLIC' ;

59253 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 989038285

------------------------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

------------------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 4687 | 443K| 139 (0)| 00:00:01 |

| 1 | INLIST ITERATOR | | | | | |

| 2 | TABLE ACCESS BY INDEX ROWID| TUNING4_TAB | 4687 | 443K| 139 (0)| 00:00:01 |

|* 3 | INDEX RANGE SCAN |IDX_TUNING4_TAB_OWNER | 4687 | | 13 (0)| 00:00:01 |

------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

3 -access("OWNER"='PUBLIC' OR "OWNER"='SYS')

Statistics

----------------------------------------------------------

0 recursive calls

0 db block gets

9581 consistent gets

0 physical reads

0 redo size

6805858 bytes sent via SQL*Net toclient

43970 bytes received via SQL*Netfrom client

3952 SQL*Net roundtrips to/fromclient

0 sorts (memory)

0 sorts (disk)

59253 rows processed

dexter@STARTREK> alter session set events '10053trace name context off ';

Session altered.

dexter@STARTREK>

从10053中看到

Access path analysis for TUNING4_TAB

***************************************

SINGLE TABLE ACCESS PATH

SingleTable Cardinality Estimation for TUNING4_TAB[TUNING4_TAB]

Column(#1): OWNER(

AvgLen: 6NDV: 31 Nulls: 0 Density: 0.032258

Table:TUNING4_TAB Alias: TUNING4_TAB

Card:Original: 72643.000000 Rounded: 4687 Computed: 4686.65 Non Adjusted: 4686.65

Rounded:

4687

实际:

59253

明显是由于统计信息不准确造成的。我们看一下它的直方图信息。

其实从执行计划

| 0 | SELECTSTATEMENT | | 4687 | 443K| 139 (0)| 00:00:01 |

也可以看到它的统计信息不准确。

确定问题根源

dexter@STARTREK> select* from user_tab_histograms where table_name='TUNING4_TAB' andcolumn_name='OWNER' ;

TABLE_NAME COLUMN_NAME ENDPOINT_NUMBERENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE

------------------------------------------------------------ --------------- --------------------------------------------

TUNING4_TAB OWNER 0 3.3913E+35

TUNING4_TAB OWNER 1 4.5831E+35

dexter@STARTREK> select table_name , column_name, histogram from user_tab_col_statistics where table_name='TUNING4_TAB' ;

TABLE_NAME COLUMN_NAME HISTOGRAM

------------------------------------------------------------ ---------------

TUNING4_TAB OWNER NONE

TUNING4_TAB OBJECT_NAME NONE

TUNING4_TAB SUBOBJECT_NAME NONE

TUNING4_TAB OBJECT_ID NONE

TUNING4_TAB DATA_OBJECT_ID NONE

TUNING4_TAB OBJECT_TYPE NONE

TUNING4_TAB CREATED NONE

TUNING4_TAB LAST_DDL_TIME NONE

TUNING4_TAB TIMESTAMP NONE

TUNING4_TAB STATUS NONE

TUNING4_TAB TEMPORARY NONE

TUNING4_TAB GENERATED NONE

TUNING4_TAB SECONDARY NONE

TUNING4_TAB NAMESPACE NONE

TUNING4_TAB EDITION_NAME NONE

15 rows selected.

没有直方图信息。

我们来直接查看表中数据的分布情况

dexter@STARTREK> select owner,count(*) fromtuning4_Tab group by owner order by 2 ;

OWNER COUNT(*)

------------------------------ ----------

OWBSYS 2

APPQOSSYS 5

SCOTT 6

SI_INFORMTN_SCHEMA 8

OUTLN 8

ORACLE_OCM 8

BI 8

ORDPLUGINS 10

PM 10

FLOWS_FILES 11

OWBSYS_AUDIT 12

DEXTER 25

APEX 33

HR 35

IX 48

DBSNMP 57

OE 112

ORDDATA 239

SH 299

EXFSYS 308

WMSYS 312

CTXSYS 384

SYSTEM 516

XDB 517

OLAPSYS 717

MDSYS 1545

APEX_030200 2251

ORDSYS 2512

SYSMAN 3392

PUBLIC 28027

SYS 31226

31 rows selected.

倾斜很严重,并且因为gather_table_stats的时候默认没有收集直方图信息,导致优化器没有选择正确的执行计划,我们来收集一下它的直方图。

默认为FOR ALL COLUMNS SIZEAUTO没有收集直方图。

dexter@STARTREK> selectdbms_stats.get_param('METHOD_OPT') from dual ;

DBMS_STATS.GET_PARAM('METHOD_OPT')

------------------------------------------------------------------------

FOR ALL COLUMNS SIZE AUTO

收集列的直方图信息

dexter@STARTREK> execdbms_stats.gather_table_stats(user,'tuning4_tab',cascade=>true,method_opt=>'FORALL columns size skewonly') ;

PL/SQL procedure successfully completed.

dexter@STARTREK> select table_name , column_name, histogram from user_tab_col_statistics where table_name='TUNING4_TAB' ;

TABLE_NAME COLUMN_NAME HISTOGRAM

------------------------------------------------------------ ---------------

TUNING4_TAB OWNER FREQUENCY

TUNING4_TAB OBJECT_NAME HEIGHT BALANCED

TUNING4_TAB SUBOBJECT_NAME FREQUENCY

TUNING4_TAB OBJECT_ID NONE

TUNING4_TAB DATA_OBJECT_ID HEIGHT BALANCED

TUNING4_TAB OBJECT_TYPE FREQUENCY

TUNING4_TAB CREATED HEIGHT BALANCED

TUNING4_TAB LAST_DDL_TIME HEIGHT BALANCED

TUNING4_TAB TIMESTAMP HEIGHT BALANCED

TUNING4_TAB STATUS FREQUENCY

TUNING4_TAB TEMPORARY FREQUENCY

TUNING4_TAB GENERATED FREQUENCY

TUNING4_TAB SECONDARY FREQUENCY

TUNING4_TAB NAMESPACE FREQUENCY

TUNING4_TAB EDITION_NAME NONE

15 rows selected.

owner为频率直方图,比较正确。

dexter@STARTREK> select * from user_tab_histograms wheretable_name='TUNING4_TAB' and column_name='OWNER' ;

TABLE_NAME COLUMN_NAME ENDPOINT_NUMBERENDPOINT_VALUE ENDPOINT_ACTUAL_VALUE

------------------------------------------------------------ --------------- -------------------------------------

TUNING4_TAB OWNER 1 3.3913E+35

TUNING4_TAB OWNER 179 3.3913E+35

TUNING4_TAB OWNER 206 3.4959E+35

TUNING4_TAB OWNER 212 3.5442E+35

TUNING4_TAB OWNER 215 3.5448E+35

TUNING4_TAB OWNER 244 3.6006E+35

TUNING4_TAB OWNER 246 3.7551E+35

TUNING4_TAB OWNER 249 3.8082E+35

TUNING4_TAB OWNER 370 4.0119E+35

TUNING4_TAB OWNER 383 4.1159E+35

TUNING4_TAB OWNER 422 4.1174E+35

TUNING4_TAB OWNER 423 4.1186E+35

TUNING4_TAB OWNER 436 4.1186E+35

TUNING4_TAB OWNER 636 4.1186E+35

TUNING4_TAB OWNER 2824 4.1711E+35

TUNING4_TAB OWNER 2855 4.3242E+35

TUNING4_TAB OWNER 5199 4.3277E+35

TUNING4_TAB OWNER 5455 4.3277E+35

TUNING4_TAB OWNER 5500 4.3277E+35

TUNING4_TAB OWNER 5525 4.5330E+35

TUNING4_TAB OWNER 5567 4.5831E+35

21 rows selected.

再次测试

已经收集好了直方图,我们再来看一下执行计划以及10053事件。

set autotrace traceonly

alter session set tracefile_identifier=histogram ;

alter session set events '10053 trace name contextforever ,level 12';

select * from tuning4_Tab where owner='SYS' orowner='PUBLIC' ;

alter session set events '10053 trace name contextoff ';

已经选择了正确、最优的执行计划。

dexter@STARTREK> set autotrace traceonly

dexter@STARTREK> alter session settracefile_identifier=histogram ;

Session altered.

dexter@STARTREK> alter session set events '10053trace name context forever ,level 12';

Session altered.

dexter@STARTREK> select * from tuning4_Tab whereowner='SYS' or owner='PUBLIC' ;

59253 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 1641193091

---------------------------------------------------------------------------------

| Id |Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

---------------------------------------------------------------------------------

| 0 |SELECT STATEMENT | | 59137 | 5601K| 291 (1)| 00:00:01 |

|* 1 | TABLE ACCESS FULL| TUNING4_TAB | 59137 | 5601K| 291 (1)| 00:00:01 |

---------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 -filter("OWNER"='PUBLIC' OR "OWNER"='SYS')

Statistics

----------------------------------------------------------

0 recursive calls

0 db block gets

4927 consistent gets

0 physical reads

0 redo size

3035580 bytes sent via SQL*Net toclient

43970 bytes received via SQL*Netfrom client

3952 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

59253 rows processed

dexter@STARTREK> alter session set events '10053trace name context off ';

Session altered.

dexter@STARTREK> exit

SINGLE TABLE ACCESS PATH

SingleTable Cardinality Estimation for TUNING4_TAB[TUNING4_TAB]

Column(#1):

NewDensity:0.000090, OldDensity:0.000007 BktCnt:5567, PopBktCnt:5565,PopValCnt:19, NDV:31

Column(#1): OWNER(

AvgLen: 6NDV: 31 Nulls: 0 Density: 0.000090

Histogram: Freq #Bkts: 21 UncompBkts: 5567 EndPtVals: 21

Table:TUNING4_TAB Alias: TUNING4_TAB

Card:Original: 72643.000000 Rounded: 59137 Computed: 59137.43 Non Adjusted: 59137.43

Rounded: 59137

比较正确了。也选择了全表扫描作为最佳的accesspath。