ソリューションシナリオのOracle顔「バインド変数を使用して傾き列データ」

1.背景情報

    私たちは、Oracleが伝統的なOLTP(オンライントランザクション処理)クラスのシステムでは、強く効果的にシステムの同時処理能力を高めるためにハード解析を減らすことができますバインド変数を、使用することを推奨し、知っています。でも、いくつかの古いシステムでは、開発段階の初めに意識の欠如は、後半に変数をバインドするために使用されていないと、変換プログラム、運用保守DBAは、CURSOR_SHARINGを設定することを余儀なくされたときにバインド変数を使用するようにシステムを強制的に=力を並行処理の量を増やすことはできません(これは最後の手段ではなく、ベストプラクティスのプログラムです)。

    バインド変数を使用してOLTPシステムに多大な恩恵をもたらしているが、また、いくつかの困難な問題をもたらす一方で、最も典型的には、SQL文がバインド変数が含まれているため、オプティマイザは、コンクリートに代表されるバインド変数の値を知ることができないですだけ正確に間違った実行計画を選択することによって引き起こされ、オプションレートの値を決定することができないことにつながる可能性があり、デフォルトの選択率を、使用しています。Oracle 9iの時代に、私たちは、この問題に対する解決策を持っている、つまりバインド変数(のぞき見をバインド)の特性をスパイ。そこには、ときにバインド変数のSQL検出され、プロパティをオンにした場合に、その第一のハード解析において、オプティマイザは正しい最終的な実行計画を選択し、正確任意率(選択率)の真の値を決定するためにスヌープします。しかし、そのためすべてのソフト/ソフト解像度の最初のハード解析後のため、別の厄介な問題を紹介すると同時に、特性、及び、再び実際のバインド変数の値に詮索ないだろう、とどこフィールド値そのものであればOracleのこの機能はデフォルトで有効になっているが偏在上の値の比は、それが(最初の値がスパイまれなケースを表している場合は特に、問題はより深刻になります)、パフォーマンス上の問題を引き起こす可能性があり、それは、でしたが、この機能に、顧客の生産環境のベストプラクティスの多くはオフになります。

    Oracle 11gの時代までは、バインドでこの問題への真の意味ソリューションと考え覗き、ACS(adaptive_cursor_sharing)特性発足しました。しかし、また、完璧ではない、より早期にバグ、ACS特性自体は確かに解決するのは難しい余分になるので、共有プールの容量要件も増加し、そのソフト解析スキャンチェーンが長くなり、子カーソルの増加につながる、とこの機能がオンになっても、Oracleのデフォルトた場合、お客様の生産環境の多くが閉鎖されます。

    傾斜カラムは、タイムリーなコミュニケーションと開発すべきデータに遭遇したバインド変数を使用している場合、この文脈では、SQLの最適化の専門家の趙ヨンジュンのコンサルティング会社は、推奨されるデータ列のように大きく歪んだ分布のか列の値が多いが、変数は最初、SQLを発行する前に、だけでなく、アプリケーション内のハード解析の言葉の多くにつながる入ってくる値を決定することができる結合しない場合は、変数を結合しない、それは非定型の値であるかどうか、そのような場合には、非SQLバインド変数を使用して、典型的な値は、文のバインド変数が使用されている場合。

    アプリケーションは、状況を変えることができない場合は?またはACSを覗い同じバインドで試してみて、オープンすることです。私は現在、(最初の非定型は、実施計画によると、より深刻な結果にパフォーマンスのリードをスパイされている防ぐの値は代表値をバインドすることができます)効率や非定型値を犠牲にしていると考えることができます特性(これらの機能は、すでに上で生産システムを閉じているか、慎重に判断をテストする場合)、実際のテスト検証は、他のパフォーマンスの問題を引き起こすことなく、問題を解決することができます。

2.テストケースの構造

    このシナリオで説明した単純なOracleの試験溶液の構成は、(+ ACSを覗い結合します):

--建表T_SKEW,构造出严重的数据倾斜:
create table jingyu.t_skew as select * from dba_objects;
create index jingyu.idx_t_skew on jingyu.t_skew(object_id);
update jingyu.t_skew set object_id=3 where object_id>3;
commit;

--查看数据列OBJECT_ID的倾斜程度:
select object_id, count(*) from jingyu.t_skew group by object_id;

 OBJECT_ID   COUNT(*)
---------- ----------
         2          1
         3      86412

--收集统计信息:
exec dbms_stats.gather_table_stats('JINGYU','T_SKEW');

--查看列OBJECT_ID的直方图信息:
select owner, table_name, column_name, histogram from dba_tab_col_statistics where table_name = 'T_SKEW' and column_name = 'OBJECT_ID';
OWNER                                                        Name            Name                      HISTOGRAM
------------------------------------------------------------ --------------- ------------------------- ------------------------------
JINGYU                                                       T_SKEW          OBJECT_ID                 FREQUENCY

    利用MOS:SCRIPT -情報を照会するためのスクリプトは、CBO(文書ID 31412.1)のためにオプティマイザ統計を表示するために選択を提供します。

SQL> @sosi
SQL> set echo off

Please enter Name of Table Owner (Null = SYS): jingyu
Please enter Table Name to show Statistics for: t_skew

***********
Table Level
***********


Table                       Number                 Empty Average    Chain Average Global User               Sample Date
Name                       of Rows   Blocks       Blocks   Space    Count Row Len Stats  Stats                Size MM-DD-YYYY
--------------- ------------------ -------- ------------ ------- -------- ------- ------ ------ ------------------ ----------
T_SKEW                      86,413    1,262            0       0        0      96 YES    NO                 86,413 08-26-2019

Column                    Column                       Distinct          Number     Number Global User               Sample Date
Name                      Details                        Values Density Buckets      Nulls Stats  Stats                Size MM-DD-YYYY
------------------------- ------------------------ ------------ ------- ------- ---------- ------ ------ ------------------ ----------
OWNER                     VARCHAR2(30)                       27       0       1          0 YES    NO                 86,413 08-26-2019
OBJECT_NAME               VARCHAR2(128)                  51,864       0       1          0 YES    NO                 86,413 08-26-2019
SUBOBJECT_NAME            VARCHAR2(30)                       87       0       1     86,152 YES    NO                    261 08-26-2019
OBJECT_ID                 NUMBER(22)                          2       0       2          0 YES    NO                  5,389 08-26-2019
DATA_OBJECT_ID            NUMBER(22)                      8,670       0       1     77,703 YES    NO                  8,710 08-26-2019
OBJECT_TYPE               VARCHAR2(19)                       44       0       1          0 YES    NO                 86,413 08-26-2019
CREATED                   DATE                              904       0       1          0 YES    NO                 86,413 08-26-2019
LAST_DDL_TIME             DATE                              995       0       1          0 YES    NO                 86,413 08-26-2019
TIMESTAMP                 VARCHAR2(19)                    1,036       0       1          0 YES    NO                 86,413 08-26-2019
STATUS                    VARCHAR2(7)                         2       1       1          0 YES    NO                 86,413 08-26-2019
TEMPORARY                 VARCHAR2(1)                         2       1       1          0 YES    NO                 86,413 08-26-2019
GENERATED                 VARCHAR2(1)                         2       1       1          0 YES    NO                 86,413 08-26-2019
SECONDARY                 VARCHAR2(1)                         2       1       1          0 YES    NO                 86,413 08-26-2019
NAMESPACE                 NUMBER(22)                         20       0       1          0 YES    NO                 86,413 08-26-2019
EDITION_NAME              VARCHAR2(30)                        0       0       0     86,413 YES    NO                        08-26-2019

                              B                                            Average     Average
Index                      Tree Leaf       Distinct             Number Leaf Blocks Data Blocks      Cluster Global User               Sample Date
Name            Unique    Level Blks           Keys            of Rows     Per Key     Per Key       Factor Stats  Stats                Size MM-DD-YYYY
--------------- --------- ----- ---- -------------- ------------------ ----------- ----------- ------------ ------ ------ ------------------ ----------
IDX_T_SKEW      NONUNIQUE     1  298              2             86,413         149         617        1,234 YES    NO                 86,413 08-26-2019

Index           Column                     Col Column
Name            Name                       Pos Details
--------------- ------------------------- ---- ------------------------
IDX_T_SKEW      OBJECT_ID                    1 NUMBER(22)

***************
Partition Level
***************

***************
SubPartition Level
***************
SQL> 

3.シナリオのテスト

まず確認bind_peekingを作り、3.1 ACSは開いた状態です

--查询隐藏参数:
set linesize 333
col name for a35
col description for a66
col value for a30
SELECT   i.ksppinm name,  
   i.ksppdesc description,  
   CV.ksppstvl VALUE
FROM   sys.x$ksppi i, sys.x$ksppcv CV  
   WHERE   i.inst_id = USERENV ('Instance')  
   AND CV.inst_id = USERENV ('Instance')  
   AND i.indx = CV.indx  
   AND i.ksppinm LIKE '%&param%' 
ORDER BY   REPLACE (i.ksppinm, '_', '');  

--相关隐藏参数的默认值(表示bind_peeking和acs都是开启的):
NAME                                DESCRIPTION                                                        VALUE
----------------------------------- ------------------------------------------------------------------ ------------------------------
_optim_peek_user_binds              enable peeking of user binds                                       TRUE
_optimizer_adaptive_cursor_sharing  optimizer adaptive cursor sharing                                  TRUE
_optimizer_extended_cursor_sharing  optimizer extended cursor sharing                                  UDO
_optimizer_extended_cursor_sharing_ optimizer extended cursor sharing for relational operators         SIMPLE
rel

3.2シナリオのテストケースとテスト結果

--1)场景测试用例
alter session set current_schema=jingyu;
alter session set statistics_level=all;
set lines 200 pages 200

var v1 number;
exec :v1 := 2;
select count(*) from t_skew where object_id = :v1;
select * from table(dbms_xplan.display_cursor(null,null,'allstats'));

exec :v1 := 3;
select count(*) from t_skew where object_id = :v1;
select * from table(dbms_xplan.display_cursor(null,null,'allstats'));

select count(*) from t_skew where object_id = :v1;
select * from table(dbms_xplan.display_cursor(null,null,'allstats'));

--2)场景测试结果
SQL> alter system flush shared_pool;
SQL> alter session set current_schema=jingyu;
SQL> alter session set statistics_level=all;
SQL> set lines 200 pages 200
SQL> 
--绑定变量值为2,第一次执行,采用INDEX RANGE SCAN的执行计划,Plan hash value: 3167530345:
SQL> var v1 number;
SQL> exec :v1 := 2;
SQL> select count(*) from t_skew where object_id = :v1;

  COUNT(*)
----------
         1
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  7mz2mhz0nq92n, child number 0
-------------------------------------
select count(*) from t_skew where object_id = :v1

Plan hash value: 3167530345

------------------------------------------------------------------------------------------
| Id  | Operation         | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |            |      1 |        |      1 |00:00:00.01 |       2 |
|   1 |  SORT AGGREGATE   |            |      1 |      1 |      1 |00:00:00.01 |       2 |
|*  2 |   INDEX RANGE SCAN| IDX_T_SKEW |      1 |     16 |      1 |00:00:00.01 |       2 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=:V1)

--绑定变量值为3,第一次执行,沿用INDEX RANGE SCAN的执行计划,Plan hash value: 3167530345:
SQL> exec :v1 := 3;
SQL> select count(*) from t_skew where object_id = :v1;

  COUNT(*)
----------
     86412
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  7mz2mhz0nq92n, child number 0
-------------------------------------
select count(*) from t_skew where object_id = :v1

Plan hash value: 3167530345

------------------------------------------------------------------------------------------
| Id  | Operation         | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |            |      2 |        |      2 |00:00:00.10 |     301 |
|   1 |  SORT AGGREGATE   |            |      2 |      1 |      2 |00:00:00.10 |     301 |
|*  2 |   INDEX RANGE SCAN| IDX_T_SKEW |      2 |     16 |  86413 |00:00:00.06 |     301 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=:V1)

--绑定变量值为3,第二次执行,变为INDEX FAST FULL SCAN的执行计划,Plan hash value: 2333720604:
SQL> select count(*) from t_skew where object_id = :v1;

  COUNT(*)
----------
     86412
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  7mz2mhz0nq92n, child number 1
-------------------------------------
select count(*) from t_skew where object_id = :v1

Plan hash value: 2333720604

----------------------------------------------------------------------------------------------
| Id  | Operation             | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |            |      1 |        |      1 |00:00:00.07 |     502 |
|   1 |  SORT AGGREGATE       |            |      1 |      1 |      1 |00:00:00.07 |     502 |
|*  2 |   INDEX FAST FULL SCAN| IDX_T_SKEW |      1 |  86389 |  86412 |00:00:00.04 |     502 |
----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("OBJECT_ID"=:V1)

SQL> 

    これは、バインド変数の値をSQL 3のときに、第2の実行、実施計画の適応調整見ることができます。

3.3シナリオのテストの詳細な分析

あなたは、カーソル情報(例えばカーソルがバインド対応またはバインドに敏感されているかどうかなど)、選択範囲を確認するために適応カーソル共有のためのV $ビューを使用して、実行統計することができます:
のV $ SQLは、カーソルが敏感に結合されているかどうかを示しますかバインド対応
V $ SQL_CS_HISTOGRAMは、三バケット実行履歴ヒストグラム全体で実行回数の分布を示す
のV $ SQL_CS_SELECTIVITYを選択を共有し、カーソルをチェックするために使用された場合は、バインド変数を含むすべての述語のために保存された選択範囲を示し
、V $ SQL_CS_STATISTICSをまとめたものオプティマイザは、カーソルがバインド対応マークするかどうかを判断するために使用する情報。

    五$のSQL CHILD_NUMBER、処刑、BUFFER_GETS、バインド敏感、バインド対応、is_shareable情報を通じてSQL(SQL_ID = '7mz2mhz0nq92n')を参照してください。

SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BS",
  2         IS_BIND_AWARE AS "BA", IS_SHAREABLE AS "SH", PLAN_HASH_VALUE
  3  FROM   V$SQL
  4  WHERE  SQL_ID = '7mz2mhz0nq92n';

CHILD_NUMBER EXECUTIONS BUFFER_GETS BS BA SH PLAN_HASH_VALUE
------------ ---------- ----------- -- -- -- ---------------
           0          2         348 Y  N  N       3167530345
           1          1         502 Y  Y  Y       2333720604

--再次分别执行绑定变量值为3和2的SQL:
SQL> select count(*) from t_skew where object_id = :v1;

  COUNT(*)
----------
     86412
SQL> exec :v1 := 2;
SQL> select count(*) from t_skew where object_id = :v1;

  COUNT(*)
----------
         1

--再次查询v$sql
CHILD_NUMBER EXECUTIONS BUFFER_GETS BS BA SH PLAN_HASH_VALUE
------------ ---------- ----------- -- -- -- ---------------
           0          2         348 Y  N  N       3167530345
           1          2        1004 Y  Y  Y       2333720604
           2          1           2 Y  Y  Y       3167530345

    (; SH 0値N、共有されていないた意味で共有されることを意味Yの値は、前記0と1と2、SH 1及び2)現在の親カーソルCHILD_NUMBER SQL 3の下ハング見ることができます。

    五$ sql_cs_によって*関連情報のACS:

--V$SQL_CS_HISTOGRAM
SQL> select * from V$SQL_CS_HISTOGRAM where sql_id = '7mz2mhz0nq92n';

ADDRESS          HASH_VALUE SQL_ID                     CHILD_NUMBER  BUCKET_ID      COUNT
---------------- ---------- -------------------------- ------------ ---------- ----------
0000000087F34700 3242927188 7mz2mhz0nq92n                         2          0          1
0000000087F34700 3242927188 7mz2mhz0nq92n                         2          1          0
0000000087F34700 3242927188 7mz2mhz0nq92n                         2          2          0
0000000087F34700 3242927188 7mz2mhz0nq92n                         1          0          0
0000000087F34700 3242927188 7mz2mhz0nq92n                         1          1          2
0000000087F34700 3242927188 7mz2mhz0nq92n                         1          2          0
0000000087F34700 3242927188 7mz2mhz0nq92n                         0          0          1
0000000087F34700 3242927188 7mz2mhz0nq92n                         0          1          1
0000000087F34700 3242927188 7mz2mhz0nq92n                         0          2          0

--V$SQL_CS_SELECTIVITY
SQL> col PREDICATE for a30
SQL> select * from V$SQL_CS_SELECTIVITY where sql_id = '7mz2mhz0nq92n';

ADDRESS          HASH_VALUE SQL_ID                     CHILD_NUMBER PREDICATE                        RANGE_ID LOW                  HIGH
---------------- ---------- -------------------------- ------------ ------------------------------ ---------- -------------------- --------------------
0000000087F34700 3242927188 7mz2mhz0nq92n                         2 =V1                                     0 0.000167             0.000204
0000000087F34700 3242927188 7mz2mhz0nq92n                         1 =V1                                     0 0.899749             1.099694
SQL> 

--V$SQL_CS_STATISTICS 
SQL> select * from V$SQL_CS_STATISTICS where sql_id = '7mz2mhz0nq92n';

ADDRESS          HASH_VALUE SQL_ID                     CHILD_NUMBER BIND_SET_HASH_VALUE PE EXECUTIONS ROWS_PROCESSED BUFFER_GETS   CPU_TIME
---------------- ---------- -------------------------- ------------ ------------------- -- ---------- -------------- ----------- ----------
0000000087F34700 3242927188 7mz2mhz0nq92n                         2          2064090006 Y           1              4           2          0
0000000087F34700 3242927188 7mz2mhz0nq92n                         1          2706503459 Y           1         172826         502          0
0000000087F34700 3242927188 7mz2mhz0nq92n                         0          2064090006 Y           1              4          49          0
SQL>

4.まとめ

    知識テストの関連ポイントを要約:
4.1バーには、SQLの実行計画をクリーンアップ

--查询SQL的ADDRESS和HASH_VALUE
SQL> select sql_id, ADDRESS, HASH_VALUE from v$sqlarea where sql_id = '7mz2mhz0nq92n';

SQL_ID                     ADDRESS          HASH_VALUE
-------------------------- ---------------- ----------
7mz2mhz0nq92n              0000000087F34700 3242927188

--清理SQL的执行计划
SQL> exec sys.DBMS_SHARED_POOL.PURGE('0000000087F34700,3242927188','C');

閉じる4.2バインド覗き特性およびACS

--均为动态参数
--bind peeking(绑定变量窥探)
alter system set "_optim_peek_user_binds"=false;

--acs(adaptive cursor sharing)
alter system set "_optimizer_extended_cursor_sharing_rel"=NONE;
alter system set "_optimizer_extended_cursor_sharing"=NONE;
alter system set "_optimizer_adaptive_cursor_sharing"=false;

    特記事項:私はここだけではfalseに設定されたパラメータを_optim_peek_user_bindsているなど、再び同じ実験手順に従って、次のようにクエリ結果があり、3.2を繰り返したバインドチラッと覗くがオフになっている場合、実際にはACSが動作しません、それは性質ACS使用されることはありません私は、対応するパラメータACSを無効にするに誇示していない場合でも:

SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BS",
  2         IS_BIND_AWARE AS "BA", IS_SHAREABLE AS "SH", PLAN_HASH_VALUE
  3  FROM   V$SQL
  4  WHERE  SQL_ID = '7mz2mhz0nq92n';

CHILD_NUMBER EXECUTIONS BUFFER_GETS BS BA SH PLAN_HASH_VALUE
------------ ---------- ----------- -- -- -- ---------------
           0          3        1506 N  N  Y       2333720604

--可以看到这3次执行执行计划都是一样的,因为受到OPT_PARAM('_optim_peek_user_binds' 'false')影响,采用了INDEX FAST FULL SCAN的执行计划,Plan hash value: 2333720604:

SQL> select * from table(dbms_xplan.display_cursor('7mz2mhz0nq92n',0,'advanced'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  7mz2mhz0nq92n, child number 0
-------------------------------------
select count(*) from t_skew where object_id = :v1

Plan hash value: 2333720604

------------------------------------------------------------------------------------
| Id  | Operation             | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |            |       |       |    82 (100)|          |
|   1 |  SORT AGGREGATE       |            |     1 |     3 |            |          |
|*  2 |   INDEX FAST FULL SCAN| IDX_T_SKEW | 43207 |   126K|    82   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / T_SKEW@SEL$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
      DB_VERSION('11.2.0.4')
      OPT_PARAM('_optim_peek_user_binds' 'false')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX_FFS(@"SEL$1" "T_SKEW"@"SEL$1" ("T_SKEW"."OBJECT_ID"))
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("OBJECT_ID"=:V1)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]

    だから、ACSの特性を開いて、だけでなく、状況のクエリバインドのぞき見を設定するかどうかを確認するとき。

おすすめ

転載: www.cnblogs.com/jyzhao/p/11415820.html