Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.misc -> Re: Getting two fields from the one table.

Re: Getting two fields from the one table.

From: mcstock <mcstockspamplug_at_spamdamenquery.com>
Date: Thu, 27 Nov 2003 09:54:35 -0500
Message-ID: <YKydnao4-rvbjVuiRVn-vg@comcast.com>


all solutions should be criticized -- (you ably demonstrate that there's a big difference between a professional critique and flaming!)

i didn't include any performance comments in my post, but i did not ignore them

good observation on the GROUP BY -- totally missed that; i often advocate from clause subqueries and this is an excellent application

my tests showed basically the same cost for a large query, and a somewhat higher cost for a smaller query -- of course, i have argued in the past that a slightly higher cost can quickly become a very costly cost depending on the frequency of execution

i ran your tests as supplied, and came up with results listed below -- but i also ran them with PK/FK indexes, fully analyzed for all 't1' rows (or x1 in my test env) and for selecting one t1 (x1) row

bottom line: it looks like the pivot approach performed better. and moving the group-by to a from clause subquery simplifies the coding. very interesting, it appears the CBO also figured out that it did not have to select all rows for the inline view (but the RBO wasn't that smart)

Execution Plan -- EXTRA JOIN SYNTAX, unindexed


   0 SELECT STATEMENT Optimizer=CHOOSE    1 0 MERGE JOIN

   2    1     MERGE JOIN
   3    2       SORT (JOIN)
   4    3         TABLE ACCESS (FULL) OF 'X2'
   5    2       SORT (JOIN)
   6    5         TABLE ACCESS (FULL) OF 'X1'
   7    1     SORT (JOIN)
   8    7       TABLE ACCESS (FULL) OF 'X2'
Statistics
        835  recursive calls
        166  db block gets
        608  consistent gets
        230  physical reads
      15824  redo size
    1334419  bytes sent via SQL*Net to client
     185351  bytes received via SQL*Net from client
       1668  SQL*Net roundtrips to/from client
          2  sorts (memory)
          1  sorts (disk)
      25000  rows processed

Execution Plan -- 'PIVOT' SYNTAX, unindexed


   0 SELECT STATEMENT Optimizer=CHOOSE    1 0 MERGE JOIN

   2    1     VIEW
   3    2       SORT (GROUP BY)
   4    3         TABLE ACCESS (FULL) OF 'X2'
   5    1     SORT (JOIN)
   6    5       TABLE ACCESS (FULL) OF 'X1'
Statistics
       1720  recursive calls
        312  db block gets
        772  consistent gets
        603  physical reads
      34588  redo size
    1334421  bytes sent via SQL*Net to client
     185351  bytes received via SQL*Net from client
       1668  SQL*Net roundtrips to/from client
          0  sorts (memory)
          2  sorts (disk)
      25000  rows processed


Your original test case (on 8.1.7 on NT Pro; no indexes, and not analyzed ) was slower for me -- but that may be due to disk sorts (sort area size was 1,000,000) any thoughts by any other posters would be welcome

However, reran ran your test case after analyzing tables (with CBO) -- then the plan and stats were similar to what i show below for indexed+analyzed selecting all rows (since the optimizer did not use the indexes)

Here's the analyzed and indexed results, CBO

Execution Plan -- ALL ROWS, EXTRA JOIN


   0 SELECT STATEMENT Optimizer=CHOOSE (Cost=57 Card=625000 Bytes =36250000)

   1 0 HASH JOIN (Cost=57 Card=625000 Bytes=36250000)

   2    1     TABLE ACCESS (FULL) OF 'X2' (Cost=17 Card=500 Bytes=7000  )
   3    1     HASH JOIN (Cost=37 Card=125000 Bytes=5500000)
   4    3       TABLE ACCESS (FULL) OF 'X2' (Cost=17 Card=500 Bytes=70 00)
   5    3       TABLE ACCESS (FULL) OF 'X1' (Cost=19 Card=25000 Bytes=
750000)
Statistics
          0  recursive calls
         36  db block gets
       2006  consistent gets
          0  physical reads
          0  redo size
    1334426  bytes sent via SQL*Net to client
     185351  bytes received via SQL*Net from client
       1668  SQL*Net roundtrips to/from client
          3  sorts (memory)
          0  sorts (disk)
      25000  rows processed

Execution Plan -- ALL ROWS, PIVOT (DECODE)


   0 SELECT STATEMENT Optimizer=CHOOSE (Cost=280 Card=12500000 Bytes=862500000)

   1 0 HASH JOIN (Cost=280 Card=12500000 Bytes=862500000)

   2    1     TABLE ACCESS (FULL) OF 'X1' (Cost=19 Card=25000 Bytes=750000)
   3    1     VIEW (Cost=192 Card=50000 Bytes=1950000)
   4    3       SORT (GROUP BY) (Cost=192 Card=50000 Bytes=700000)
   5    4         TABLE ACCESS (FULL) OF 'X2' (Cost=17 Card=50000
Bytes=700000)
Statistics
        850  recursive calls
        180  db block gets
        495  consistent gets
        373  physical reads
      18576  redo size
    1334421  bytes sent via SQL*Net to client
     185351  bytes received via SQL*Net from client
       1668  SQL*Net roundtrips to/from client
          3  sorts (memory)
          1  sorts (disk)
      25000  rows processed


Execution Plan -- SINGLE ROW, EXTRA JOIN


   0 SELECT STATEMENT Optimizer=CHOOSE (Cost=14 Card=25 Bytes=1450)    1 0 MERGE JOIN (CARTESIAN) (Cost=14 Card=25 Bytes=1450)

   2    1     NESTED LOOPS (Cost=4 Card=5 Bytes=220)
   3    2       TABLE ACCESS (BY INDEX ROWID) OF 'X1' (Cost=2 Card=1
Bytes=30)
   4    3         INDEX (UNIQUE SCAN) OF 'X1$PK' (UNIQUE) (Cost=1 Card=250)
   5    2       TABLE ACCESS (BY INDEX ROWID) OF 'X2' (Cost=2 Card=5
Bytes=70)
   6    5         INDEX (RANGE SCAN) OF 'X2$ID' (NON-UNIQUE) (Cost=1 Card=5)
   7    1     SORT (JOIN) (Cost=12 Card=5 Bytes=70)
   8    7       TABLE ACCESS (BY INDEX ROWID) OF 'X2' (Cost=2 Card=5
Bytes=70)
   9    8         INDEX (RANGE SCAN) OF 'X2$ID' (NON-UNIQUE) (Cost=1 Card=5)
Statistics
          0  recursive calls
          0  db block gets
         11  consistent gets
          0  physical reads
          0  redo size
        483  bytes sent via SQL*Net to client
        425  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          4  sorts (memory)
          0  sorts (disk)
          1  rows processed


Execution Plan -- SINGLE ROW, PIVOT (DECODE)


   0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=500 Bytes=34500)    1 0 NESTED LOOPS (Cost=4 Card=500 Bytes=34500)

   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'X1' (Cost=2 Card=1 Bytes=30)
   3    2       INDEX (UNIQUE SCAN) OF 'X1$PK' (UNIQUE) (Cost=1 Card=250)
   4    1     VIEW
   5    4       SORT (GROUP BY) (Cost=2 Card=500 Bytes=7000)
   6    5         TABLE ACCESS (BY INDEX ROWID) OF 'X2' (Cost=2 Card=500
Bytes=7000)
   7    6           INDEX (RANGE SCAN) OF 'X2$ID' (NON-UNIQUE) (Cost=1
Card=500)

Statistics


          0  recursive calls
          0  db block gets
          6  consistent gets
          0  physical reads
          0  redo size
        485  bytes sent via SQL*Net to client
        425  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

Thanks for the criticism!

"VC" <boston103_at_hotmail.com> wrote in message news:J8bxb.313446$HS4.2773419_at_attbi_s01...
| Hello Mark.
|
| What follows below is not intended to criticize your solution. Just a
| couple of remarks:
|
| Given:
|
| /* Items */
| create table t1 as select object_name name, object_id id from all_objects
| where rownum <=25000;
| /* Prices */
| create table t2 as select id, class, round(dbms_random.value*100) price
from
| (select rownum class from user_objects where rownum <=2) b,
| (select object_id id from all_objects where rownum <=25000) a
|
|
| /* Join solution */
| select t1.name, a.price, b.price
| from t1, t2 a, t2 b
| where t1.id=a.id and a.class=1
| and t1.id=b.id and b.class=2
|
| /* Pivot solution */
| select name,price1, price2
| from t1,
| (select id,
| max(decode(class, 1, price, null)) price1,
| max(decode(class, 2, price, null)) price2
| from t2 group by id) t2
| where t1.id=t2.id
|
| 1. The 'pivot' approach is more performant because the number of LIOs is
| about 50% lower in comparison to the 'join' solution (set autottrace on).
| The performance advantage would be even higher if one wanted to 'flatten'
| more than two prices because one would need to join the prices table as
| many times as there are different prices per item.
|
| 2. It's not necessary to 'group by ' all the select columns -- one needs
to
| flatten only the price table (see above).
|
| Rgds.
|
Received on Thu Nov 27 2003 - 08:54:35 CST

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US