0

私のマスターテーブルUDBMOVEMENT_ORIG(26mil.rows)と(18mil.rows)で、いくつかのデフォルト条件とこれらのマスターテーブルの結合条件を満たすUDBIDENTDATA_ORIGマテリアライズドビューTMP_MS_UDB_MV(このオブジェクトの同義語)が作成され、dbでの奇妙な動作が怖いです。UDBMOVEMENTMVは約1200万行を取得しました。私はそれほど巨大ではないオブジェクトをクエリするためにMVを作成しました、MVは3GB、マスターテーブルは12GBを取得しました。しかし、物理的な読み取りと一貫した取得でさえ、マスターテーブルよりもMVの方が少なく、マスターテーブルでは最終的な実行時間が短いことを理解していません。以下の私のログを参照してください。

なんで?

SQL> set echo on
SQL> @flush
SQL> alter system flush buffer_cache;

System altered.

Elapsed: 00:00:00.20
SQL> alter system flush shared_pool;

System altered.

Elapsed: 00:00:00.65
SQL> SELECT
2 UDBMovement.zIdDevice, UDBMovement.sDevice, UDBMovement.zIdLocal, UDBMovement.sComputer, UDBMovement.tActionTime, UDBIdentData.sCardSubType, UDBIdentData.sCardType, UDBMovement.cEpan, UDBMovement.cText, UDBMovement.lArtRef, UDBMovement.sArtClassRef, UDBMovement.lSequenz, UDBMovement.sTransMark, UDBMovement.lBlock, UDBMovement.sTransType, UDBMovement.lGlobalID, UDBMovement.sFacility, UDBIdentData.sCardClass, UDBMovement.lSingleAmount, UDBMovement.sVAT, UDBMovement.lVATTot, UDBIdentData.tTarifTimeStart, UDBIdentData.tTarifTimeEnd, UDBIdentData.cLicensePlate, UDBIdentData.lMoneyValue, UDBIdentData.lPointValue, UDBIdentData.lTimeValue, UDBIdentData.tProdTime, UDBIdentData.tExpireDate
3 FROM UDBMOVEMENT_orig UDBMovement, Udbidentdata_orig UDBIdentData
4 WHERE
5 UDBMovement.lGlobalId = UDBIdentData.lGlobalRef(+) AND UDBMovement.sComputer = UDBIdentData.sComputer(+)
6 AND UDBMovement.sTransType > 0 AND UDBMovement.sDevice < 1000 AND UDBMovement.sDevice>= 0 AND UDBIdentData.sCardType IN (2) AND (bitand(UDBMovement.sSaleFlag,1) = 0 AND bitand(UDBMovement.sSaleFlag,4) = 0) AND UDBMovement.sArtClassRef < 100
7 AND UDBMovement.tActionTime >= TO_DATE('05/05/2011 00:00:00', 'dd/mm/yyyy hh24:mi:ss') + 0.25 AND UDBMovement.tActionTime < TO_DATE('05/05/2011 00:00:00', 'dd/mm/yyyy hh24:mi:ss') + 0.5
8 ORDER BY tActionTime, lBlock, lSequenz;

4947 rows selected.

Elapsed: 00:00:15.84

Execution Plan
Plan hash value: 1768406139

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

0    SELECT STATEMENT        7166    1238K       20670 (1)   00:04:09
1    SORT ORDER BY       7166    1238K   1480K   20670 (1)   00:04:09
2    NESTED LOOPS                        
3    NESTED LOOPS        7166    1238K       20388 (1)   00:04:05
* 4  TABLE ACCESS BY INDEX ROWID     UDBMOVEMENT_ORIG    7142    809K        7056 (1)    00:01:25
* 5  INDEX RANGE SCAN    IDX_UDBMOVARTICLE   10709           61 (0)  00:00:01
* 6  INDEX UNIQUE SCAN   UDBIDENTDATA_PRIM   1           1 (0)   00:00:01
* 7  TABLE ACCESS BY INDEX ROWID     UDBIDENTDATA_ORIG   1   61      2 (0)   00:00:01


Predicate Information (identified by operation id):

4 - filter("UDBMOVEMENT"."STRANSTYPE">0 AND "UDBMOVEMENT"."SDEVICE"<1000 AND
BITAND("SSALEFLAG",1)=0 AND "UDBMOVEMENT"."SDEVICE">=0 AND BITAND("UDBMOVEMENT"."SSALEFLAG",4)=0)
5 - access("UDBMOVEMENT"."TACTIONTIME">=TO_DATE(' 2011-05-05 06:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "UDBMOVEMENT"."TACTIONTIME"<TO_DATE(' 2011-05-05 12:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "UDBMOVEMENT"."SARTCLASSREF"<100)
filter("UDBMOVEMENT"."SARTCLASSREF"<100)
6 - access("UDBMOVEMENT"."LGLOBALID"="UDBIDENTDATA"."LGLOBALREF" AND
"UDBMOVEMENT"."SCOMPUTER"="UDBIDENTDATA"."SCOMPUTER")
7 - filter("UDBIDENTDATA"."SCARDTYPE"=2)
Statistics
543 recursive calls
0 db block gets
84383 consistent gets
4485 physical reads
0 redo size
533990 bytes sent via SQL*Net to client
3953 bytes received via SQL*Net from client
331 SQL*Net roundtrips to/from client
86 sorts (memory)
0 sorts (disk)
4947 rows processed

SQL> @flush
SQL> alter system flush buffer_cache;

System altered.

Elapsed: 00:00:00.12
SQL> alter system flush shared_pool;

System altered.

Elapsed: 00:00:00.74
SQL> SELECT UDBMovement.zIdDevice, UDBMovement.sDevice, UDBMovement.zIdLocal, UDBMovement.sComputer, UDBMovement.tActionTime, UDBMovement.sCardSubType, UDBMovement.sCardType, UDBMovement.cEpan, UDBMovement.cText, UDBMovement.lArtRef, UDBMovement.sArtClassRef, UDBMovement.lSequenz, UDBMovement.sTransMark, UDBMovement.lBlock, UDBMovement.sTransType, UDBMovement.lGlobalID, UDBMovement.sFacility, UDBMovement.sCardClass, UDBMovement.lSingleAmount, UDBMovement.sVAT, UDBMovement.lVATTot, UDBMovement.tTarifTimeStart, UDBMovement.tTarifTimeEnd, UDBMovement.cLicensePlate, UDBMovement.lMoneyValue, UDBMovement.lPointValue, UDBMovement.lTimeValue, UDBMovement.tProdTime
2 FROM UDBMOVEMENT WHERE
3 UDBMovement.sTransType > 0 AND UDBMovement.sDevice < 1000 AND UDBMovement.sDevice>= 0 AND UDBMovement.sCardType IN (2) AND (bitand(UDBMovement.sSaleFlag,1) = 0 AND bitand(UDBMovement.sSaleFlag,4) = 0) AND UDBMovement.sArtClassRef < 100
4 AND UDBMovement.tActionTime >= TO_DATE('05/05/2011 00:00:00', 'dd/mm/yyyy hh24:mi:ss') + 0.25
5 AND UDBMovement.tActionTime < TO_DATE('05/05/2011 00:00:00', 'dd/mm/yyyy hh24:mi:ss') + 0.5 ORDER BY tActionTime, lBlock, lSequenz;

4947 rows selected.

Elapsed: 00:00:26.46

Execution Plan
Plan hash value: 3648898312

Id   Operation   Name    Rows    Bytes   Cost (%CPU)     Time

0    SELECT STATEMENT        2720    443K    2812 (1)    00:00:34
1    SORT ORDER BY       2720    443K    2812 (1)    00:00:34
* 2  MAT_VIEW ACCESS BY INDEX ROWID  TMP_MS_UDB_MV   2720    443K    2811 (1)    00:00:34
* 3  INDEX RANGE SCAN    EEETMP_MS_ACTTIMEDEVICE     2732        89 (0)  00:00:02


Predicate Information (identified by operation id):

2 - filter("UDBMOVEMENT"."STRANSTYPE">0 AND BITAND("UDBMOVEMENT"."SSALEFLAG",4)=0 AND
BITAND("SSALEFLAG",1)=0 AND "UDBMOVEMENT"."SARTCLASSREF"<100)
3 - access("UDBMOVEMENT"."TACTIONTIME">=TO_DATE(' 2011-05-05 06:00:00', 'syyyy-mm-dd
hh24:mi:ss') AND "UDBMOVEMENT"."SDEVICE">=0 AND "UDBMOVEMENT"."SCARDTYPE"=2 AND
"UDBMOVEMENT"."TACTIONTIME"<TO_DATE(' 2011-05-05 12:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
"UDBMOVEMENT"."SDEVICE"<1000)
filter("UDBMOVEMENT"."SCARDTYPE"=2 AND "UDBMOVEMENT"."SDEVICE"<1000 AND
"UDBMOVEMENT"."SDEVICE">=0)
Statistics
449 recursive calls
0 db block gets
6090 consistent gets
2837 physical reads
0 redo size
531987 bytes sent via SQL*Net to client
3953 bytes received via SQL*Net from client
331 SQL*Net roundtrips to/from client
168 sorts (memory)
0 sorts (disk)
4947 rows processed

SQL> spool off

回答ありがとうございます。

4

2 に答える 2

3

すべてのテーブル/MVに適切な統計が収集されていると想定します。

最初のクエリの計画を見ると、RANGE SCANがオンになっていることがわかります。UDBMOVEMENT_ORIG次に、where句を通過する行が見つかるたびに、INDEX UNIQUE SCANがUDBIDENTDATA_ORIG(おそらくそのPK)に向かっています。OracleがOUTERJOINを標準のINNERJOIN(NESTED LOOP)に変換したことに注意してください。

最初のステップは数行(<10k)を返すため、2番目のステップはほとんど時間がかかりません。したがって、最初のクエリの作業のほとんどは、where句の基準に一致する行の検索に費やされていると想定できます。DBはIDX_UDBMOVARTICLEインデックスの使用を選択しました。TACTIONTIME, SARTCLASSREFその定義が欠落していますが、クエリプランのおかげで、列()をカバーしていると推測できます。

2番目のクエリはストレートRANGE INDEX SCANであり、インデックス定義が欠落していますが、これも列()をカバーしていると推測できますTACTIONTIME, SDEVICE, SCARDTYPE, SDEVICE


私の結論は、元のテーブルとそのMVに同じインデックスがないため、クエリ時間(リンゴとオレンジ)に違いが見られるのは当然のことです。皮肉なことに、このクエリの対応するインデックスよりも小さい元のインデックスの方が適切です。

また、データベースは結合に非常に優れており、ほとんどのクエリでは、事前に結合されたテーブルからのわずかな利益しか見られないことも指摘しておきます。MVが非正規化されて大きくなるため、マイナスのゲインが見られることもあります(したがって、フルスキャンの方がコストがかかります)。

于 2013-02-05T09:52:01.650 に答える
0

ソート統計を見ると、遅いクエリは速いクエリのほぼ2倍のソート数を実行しています。

86 sorts (memory)

vs

168 sorts (memory)

これは、2番目のクエリが遅い理由を説明するのに役立ちますが、並べ替えだけが原因ではないかと思います。時間の増加の理由は、おそらくVincentが特定したインデックスの違いに関連しています。全体的に遅くなる理由はいくつかあると思います。

于 2013-02-05T12:34:19.137 に答える