문제

I am afraid of strange behavior in db, on my master tables UDBMOVEMENT_ORIG (26mil.rows) and UDBIDENTDATA_ORIG (18mil.rows) is created materialized view TMP_MS_UDB_MV (UDBMOVEMENT is synonym to this object) which meets some default conditions and join condition on these master tables. MV got about 12milions rows. I created MV to query not so huge objects, MV got 3GB, master tables toghether 12GB. But I don't understand that even physical reads and consistent gets are less on MV than on master tables, the final execution time is shorter on master tables. See my log below.

Why?

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

Thanks for answers.

도움이 되었습니까?

해결책 2

If you look at the sorts statistic, the slower query is doing nearly double the number of sorts than the faster query:

86 sorts (memory)

vs

168 sorts (memory)

This will go some way to explaining why the second query is slower, though I doubt the sorting alone is the entire cause. The reason for the increased time is probably related to the difference in the indexes that Vincent's identified. I suspect there's a number of reasons which add up to make it slower overall.

다른 팁

I'll assume that all tables/MV have appropriate statistics gathered.

If you look at the plan of the first query, you'll see that we have a RANGE SCAN on UDBMOVEMENT_ORIG and then for each row found that pass the where clause, we have an INDEX UNIQUE SCAN towards UDBIDENTDATA_ORIG (probably its PK). Note that Oracle has transformed your OUTER JOIN into a standard INNER JOIN (NESTED LOOP).

The first step returns few rows (<10k), therefore the second step takes next to no time. So we can assume that most of the work of the first query is spent looking for rows that match the criterias of the where clause. The DB chose to use the IDX_UDBMOVARTICLE index. We're missing its definition but we can guess that it covers the columns (TACTIONTIME, SARTCLASSREF) thanks to the query plan.

The second query is a straight RANGE INDEX SCAN and again we're missing the index definition, but again we can guess that it covers the columns (TACTIONTIME, SDEVICE, SCARDTYPE, SDEVICE).


My conclusion is that you don't have the same indexes on the original table and its MV, so it's no surprise that you're seeing differences in query time (apples and oranges). Ironically the smaller original index is more appropriate than its counterpart for this query.

I would also point that databases are very good at joining, and in most queries you will see only marginal gains from pre-joining tables. You could even see negative gains sometimes because the MV will be de-normalized and therefore larger (thus more expensive to full scan).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top