Simple XML (XPATH) 'nested loop' possible?

What's the best way to output the entries of an XML file with
the following structure as a nested list (actually it needs to
become a form where all entries can be checked).
I can output each level (see code) but it seems not to be
possible to nest the for-loops.
Any hints if it's possible with XPath directly or do I need
to save the result of one loop to output within the other or would
it even be better to make a query out of the XML result?

Thanks, great!
I tried it somwhere along this before but it didn't work
then. I propably just forgot to put the pound signes to the correct
place or something ;-)
But yes, your solution is exactly what I was looking for!
Thank you

Similar Messages

  • XML nested Loop?

    hi all.
    I´ve just completed a little test for making a tree
    component with custom
    icons / bransch.
    However, i can only get my first branch to show custom
    icons.(links -
    document) I figure I need to make a nested loop to Iterate
    over
    nextSibling?. I tried ALOT, but i guess I´m doing
    something completely
    wrong.
    here is code for my tree so far:
    my_xml = new XML();
    my_xml.ignoreWhite = true;
    my_xml.load("tree.xml");
    my_xml.onLoad = function(){
    myTree.dataProvider = this.firstChild;
    var folders = my_xml.firstChild.firstChild;
    var docs = folders.childNodes;
    for (var i=0; i < docs.length; i++){
    currDoc = docs
    trace(docs);
    var docIcon = currDoc.attributes.pic;
    switch(docIcon){
    case "pdf":
    myTree.setIcon(currDoc, "pdfIcon");
    break;
    case "word":
    myTree.setIcon(currDoc, "wordIcon");
    break;
    case "excel":
    myTree.setIcon(currDoc, "excelIcon");
    break;
    case "ie":
    myTree.setIcon(currDoc, "ieIcon");
    break;
    }//switch
    } //for
    };//onLoad
    And here is the XML I used:
    <node label="» Dokument typer">
    <node label="» links - document">
    <node label="test.url" url="
    http://www." pic="ie" info="test text" />
    <node label="test.doc" url="test.doc" pic="word"
    info="test text" />
    <node label="test.excel" url="test.xls" pic="excel"
    info="test text" />
    <node label="test.pdf" url="test.pdf" pic="pdf"
    info="test text." />
    </node>
    <node label="» Links - document">
    <node label="test URL" url="
    http://www." pic="ie" info="test text."
    />
    <node label="test URL" url="
    http://www." pic="ie" info="test text."
    />
    </node>
    </node>

    Solved it ..works nicely :D
    ty anyways.
    //cleaner
    "cLeAnEr" <[email protected]> skrev i meddelandet
    news:ekm1vc$r8h$[email protected]..
    > hi all.
    >
    > I´ve just completed a little test for making a tree
    component with custom
    > icons / bransch.
    > However, i can only get my first branch to show custom
    icons.(links -
    > document) I figure I need to make a nested loop to
    Iterate over
    > nextSibling?. I tried ALOT, but i guess I´m doing
    something completely
    > wrong.
    >
    >
    > here is code for my tree so far:
    >
    > my_xml = new XML();
    > my_xml.ignoreWhite = true;
    > my_xml.load("tree.xml");
    >
    > my_xml.onLoad = function(){
    > myTree.dataProvider = this.firstChild;
    >
    >
    > var folders = my_xml.firstChild.firstChild;
    > var docs = folders.childNodes;
    >
    > for (var i=0; i < docs.length; i++){
    > currDoc = docs
    > trace(docs);
    >
    > var docIcon = currDoc.attributes.pic;
    >
    > switch(docIcon){
    > case "pdf":
    > myTree.setIcon(currDoc, "pdfIcon");
    > break;
    > case "word":
    > myTree.setIcon(currDoc, "wordIcon");
    > break;
    > case "excel":
    > myTree.setIcon(currDoc, "excelIcon");
    > break;
    > case "ie":
    > myTree.setIcon(currDoc, "ieIcon");
    > break;
    > }//switch
    > } //for
    > };//onLoad
    >
    >
    > And here is the XML I used:
    >
    > <node label="» Dokument typer">
    > <node label="» links - document">
    > <node label="test.url" url="
    http://www." pic="ie" info="test text" />
    > <node label="test.doc" url="test.doc" pic="word"
    info="test text" />
    > <node label="test.excel" url="test.xls" pic="excel"
    info="test text" />
    > <node label="test.pdf" url="test.pdf" pic="pdf"
    info="test text." />
    > </node>
    > <node label="» Links - document">
    > <node label="test URL" url="
    http://www." pic="ie" info="test text."
    />
    > <node label="test URL" url="
    http://www." pic="ie" info="test text."
    />
    > </node>
    > </node>
    >

  • Nested loop vs Hash Join

    Hi,
    Both the querys are returning same results, but in my first query hash join and second query nested loop . How ? PLs explain
    select *
    from emp a,dept b
    where a.deptno=b.deptno and b.deptno>20;
    6 rows
    Plan hash value: 4102772462
    | Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT             |         |     6 |   348 |     6  (17)| 00:00:01 |
    |*  1 |  HASH JOIN                   |         |     6 |   348 |     6  (17)| 00:00:01 |
    |   2 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     3 |    60 |     2   (0)| 00:00:01 |
    |*  3 |    INDEX RANGE SCAN          | PK_DEPT |     3 |       |     1   (0)| 00:00:01 |
    |*  4 |   TABLE ACCESS FULL          | EMP     |     7 |   266 |     3   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       1 - access("A"."DEPTNO"="B"."DEPTNO")
       3 - access("B"."DEPTNO">20)
       4 - filter("A"."DEPTNO">20)
    select *
    from emp a,dept b
    where a.deptno=b.deptno and b.deptno=30;  
    6 rows
    Plan hash value: 568005898
    | Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
    |   0 | SELECT STATEMENT             |         |     5 |   290 |     4   (0)| 00:00:01 |
    |   1 |  NESTED LOOPS                |         |     5 |   290 |     4   (0)| 00:00:01 |
    |   2 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    20 |     1   (0)| 00:00:01 |
    |*  3 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |
    |*  4 |   TABLE ACCESS FULL          | EMP     |     5 |   190 |     3   (0)| 00:00:01 |
    Predicate Information (identified by operation id):
       3 - access("B"."DEPTNO"=30)
       4 - filter("A"."DEPTNO"=30)

    Hi,
    Unless specifically requested, Oracle picks the best execution plan based on estimates of table sizes, column selectivity and many other variables. Even though Oracle does its best to have the estimates as accurate as possible, they are frequently different, and in some cases quite different, from the actual values.
    In the first query, Oracle estimated that the predicate “ b.deptno>20” would limit the number of records to 6, and based on that it decided the use Hash Join.
    In the second query, Oracle estimated that the predicate “b.deptno=30” would limit the number of records to 5, and based on that it decided the use Nested Loops Join.
    The fact that the actual number of records is the same is irrelevant because Oracle used the estimate, rather the actual number of records to pick the best plan.
    HTH,
    Iordan
    Iotzov

  • Several nested loop at the same level in an execution plan

    Hi, I am using 11gR2, and I've seen a execution plan in the trace of my SQL query (also shown in pl/sql explain plan) with 4 nested loops all at the same level, what does this mean?
    i.e.
    - SELECT STATEMENT, GOAL = FIRST_ROWS
    + NESTED LOOPS
    + NESTED LOOPS
    + NESTED LOOPS
    + NESTED LOOPS
    each NESTED LOOP can be expanded to 2 further actions, which make sense to me. e.g.
    + NESTED LOOPS
    + TABLE ACCESS BY INDEX ROWID
    + TABLE ACCESS BY INDEX ROWID
    THANKS
    Ye

    >
    why there are 4 Nested Loops
    what is the final result set for the SELECT statement come from (any one of the 4)
    the query run so slow in 11R2
    >
    So far you are the only one who knows what the query and execution plan are because you haven't posted them
    >
    Then you need to post the query, tell us what indexes are on the join columns and post the complete plan.
    >
    We can't even begin to explain why Oracle might have chosen the plan it did if we can't see the query and plan you want explained.
    And if we only see the plan we might be able to tell you what Oracle is doing but without knowing what indexes might be on the join columns and the filter criteria columns we can't tell you why Oracle chose the plan it chose.
    And the excerpt of the plan you did provide is incomplete. You removed the indenting possibly because you did not enclose it in 'code' tags (see the FAQ).
    >
    - SELECT STATEMENT, GOAL = FIRST_ROWS
    + NESTED LOOPS
    + NESTED LOOPS
    + NESTED LOOPS
    + NESTED LOOPS
    >
    There can't be four nested loops like that at the top level since the top level will be combining the result sets from it's children. A nested loop will have two children; like the last part you showed:
    >
    + NESTED LOOPS
    + TABLE ACCESS BY INDEX ROWID
    + TABLE ACCESS BY INDEX ROWID
    >
    The two 'TABLE ACCESS ...' will be indented on a normal plan.
    Without the query and plan there isn't much we can tell you.

  • Explain Plan shows Nested Loops, Is it good or bad?

    Hi All,
    I have a doubt in the explain plan, I would like to know if the Nested Loops , will it degrade the query performance?
    Note: I have pasted only few output that I had taken from the expalin plan.
    Do let me know if there is any article I could read to get clear understanding about the same.
    17 NESTED LOOPS ANTI Cost: 125 Bytes: 186 Cardinality: 1                                                                  
    15 NESTED LOOPS ANTI Cost: 124 Bytes: 166 Cardinality: 1                                                             
    12 NESTED LOOPS Cost: 122 Bytes: 140 Cardinality: 1                                                        
         9 NESTED LOOPS Cost: 121 Bytes: 117 Cardinality: 1           
    Thanks

    Hi,
    there is absolutely nothing wrong about nested loops (NL). It's a very efficient way of combining data from two rowsources. It works pretty much like a regular loop: it takes all rows from one rowsource (the "outer" one) and for each of them it looks up a row matching the join condition in the other rowsource (the "inner" one).
    Note that there are not so many alternatives in Oracle: there are only 3 ways to join data in Oracle, and one of them is used in rather special circumstances (merge join). So normally the choice is between a NL and a hash join. Hash join (HJ) takes the smaller dataset and builds an in-memory lookup table using a hash function on join column(s). Then it goes through the other dataset and as it goes, it applies the hashing function to join column(s) and picks the matching rows from the smaller dataset.
    Actually, hash joins and nested loops are not all that different. The basic mechanism is same: you go through one datasource and as you go, you pick matching rows from the other and do the join. The main difference is that a HJ requires some preparation work (it costs resources to build the in-memory table) and thus HJ are typically associated with less-selective queries and full table scans.
    In your particular case it's nor possible to tell whether or not NL is in order based on just a few rows from the explain plan. We need to know the structure of your tables (the DDL), what kind of data they hold (optimizer stats) and what query you are running to be able to tell.
    Best regards,
    Nikolay

  • Hi how to avoid nested loops in this program to improve the performence

    Hi all
    How to avoide the nested loops in this programing what is the replacement for the nested loops in this program coding......
    LOOP AT itb_ekpo.
        READ TABLE itb_marc WITH KEY
           matnr = itb_ekpo-matnr
           werks = itb_ekpo-werks BINARY SEARCH.
        CHECK sy-subrc = 0.
    FAE 26446 fin remplacement
        itb_pca-ebeln = itb_ekpo-ebeln.
        itb_pca-ebelp = itb_ekpo-ebelp.
      itb_pca-lifnr = itb_ekko-lifnr.   "-FAE26446
        itb_pca-lifnr = itb_ekpo-lifnr.                         "+FAE26446
        itb_pca-ekgrp = itb_ekpo-ekgrp.                         "+FAE26446
        itb_pca-dispo = itb_ekpo-dispo.                         "+FAE26446
        itb_pca-matnr = itb_ekpo-matnr.
        itb_pca-werks = itb_ekpo-werks.
      Recherche du libellé article
        READ TABLE itb_makt
                   WITH KEY matnr = itb_ekpo-matnr
                            spras = text-fra
                   BINARY SEARCH.
        IF sy-subrc = 0.
          itb_pca-maktx = itb_makt-maktx.
        ELSE.
          READ TABLE itb_makt
                    WITH KEY matnr = itb_ekpo-matnr
                             spras = text-ang
                    BINARY SEARCH.
          IF sy-subrc = 0.
            itb_pca-maktx = itb_makt-maktx.
          ENDIF.
        ENDIF.
        IF NOT itb_ekpo-bpumn IS INITIAL.
          itb_pca-menge = itb_ekpo-menge * itb_ekpo-bpumz /
                                           itb_ekpo-bpumn.
        ENDIF.
      Sélect° ds la table EKES des dates de livraisons et des qtés
      en transit
        CLEAR w_temoin_ar.
        CLEAR w_etens.
        LOOP AT itb_ekes
                FROM w_index_ekes.
          IF  itb_ekes-ebeln = itb_ekpo-ebeln
          AND itb_ekes-ebelp = itb_ekpo-ebelp.
            IF itb_ekes-ebtyp = text-arn.
              itb_pca-eindt = itb_ekes-eindt.
              w_temoin_ar = 'X'.
            ELSE.
            Si c'est une qté en transit alors on recupere
            la quantité et la date.
              IF itb_ekes-dabmg < itb_ekes-menge.
                itb_pca-qtran = itb_pca-qtran + itb_ekes-menge -
                                itb_ekes-dabmg.
              ENDIF.
              IF itb_ekes-etens > w_etens.
                w_etens = itb_ekes-etens.
                itb_pca-dtran = itb_ekes-eindt.
              ENDIF.
            ENDIF.
          ELSEIF itb_ekes-ebeln > itb_ekpo-ebeln
          OR ( itb_ekes-ebeln = itb_ekpo-ebeln
          AND itb_ekes-ebelp > itb_ekpo-ebelp ).
            w_index_ekes = sy-tabix.
            EXIT.
          ENDIF.
        ENDLOOP.
      S'il n'y a pas d'AR alors récupérat° de la date livraison dans EKET.
        LOOP AT itb_eket
                FROM w_index_eket.
          IF  itb_eket-ebeln = itb_ekpo-ebeln
          AND itb_eket-ebelp = itb_ekpo-ebelp.
            IF w_temoin_ar IS INITIAL.
              itb_pca-eindt = itb_eket-eindt.
            ENDIF.
            itb_pca-slfdt = itb_eket-slfdt.
          Calcul du portefeuille fournisseur à partir de la
          qté commandée et la qté reçue
            itb_pca-attdu = itb_pca-attdu + itb_eket-menge -
                            itb_eket-wemng.
          Calcul du montant du poste
            itb_pca-netpr = itb_ekpo-netpr * itb_pca-attdu.
            IF itb_ekpo-peinh NE 0.
              itb_pca-netpr = itb_pca-netpr / itb_ekpo-peinh.
            ENDIF.
          Calcul quantité réceptionnée.
            itb_pca-wemng = itb_pca-wemng + itb_eket-wemng.
          Calcul du retard en nombre de jours calendaires
          Le calcul du retard  ne doit pas prendre en compte
          le jour de livraison
            ADD 1 TO itb_eket-eindt.
            IF NOT itb_pca-attdu  IS INITIAL
            AND    itb_eket-eindt LT sy-datum.
            Calcul du retard en nombre de jours ouvrés
              CLEAR w_retard.
              CALL FUNCTION 'Z_00_BC_WORKDAYS_PER_PERIOD'
                   EXPORTING
                        date_deb = itb_eket-eindt
                        date_fin = sy-datum
                   IMPORTING
                        jours    = w_retard.
              itb_pca-rtard = itb_pca-rtard + w_retard .
            ENDIF.
          ELSEIF itb_eket-ebeln > itb_ekpo-ebeln
          OR (   itb_eket-ebeln = itb_ekpo-ebeln
          AND    itb_eket-ebelp > itb_ekpo-ebelp ).
            w_index_eket = sy-tabix.
            EXIT.
          ENDIF.
        ENDLOOP.
      Recherche de la derniere date de livraison.
        LOOP AT itb_mseg
                FROM w_index_mseg.
          IF  itb_mseg-ebeln = itb_ekpo-ebeln
          AND itb_mseg-ebelp = itb_ekpo-ebelp.
            READ TABLE itb_mkpf
                       WITH KEY mblnr = itb_mseg-mblnr
                                mjahr = itb_mseg-mjahr
                       BINARY SEARCH.
            IF sy-subrc = 0.
              IF itb_mkpf-bldat > itb_pca-bldat.
                itb_pca-bldat = itb_mkpf-bldat.
              ENDIF.
            ENDIF.
          ELSEIF itb_mseg-ebeln > itb_ekpo-ebeln
          OR (   itb_mseg-ebeln = itb_ekpo-ebeln
          AND    itb_mseg-ebelp > itb_ekpo-ebelp ).
            w_index_mseg = sy-tabix.
            EXIT.
          ENDIF.
        ENDLOOP.
        APPEND itb_pca.
        CLEAR itb_pca.
    FAE26446 suppression parag. suivant
         ELSEIF itb_ekpo-ebeln > itb_ekko-ebeln.
           w_index_ekpo = sy-tabix.
           EXIT.
         ENDIF.
       ENDLOOP.
    Fin FAE26446
      ENDLOOP.
    Thanks in advance for all.....

    Hi
    these are the performance tips
    Instead of using nested Select loops it is often better to use subqueries.
    SELECT * FROM SPFLI
      INTO TABLE T_SPFLI
      WHERE CITYFROM = 'FRANKFURT'
        AND CITYTO = 'NEW YORK'.
    SELECT * FROM SFLIGHT AS F
        INTO SFLIGHT_WA
        FOR ALL ENTRIES IN T_SPFLI
        WHERE SEATSOCC < F~SEATSMAX
          AND CARRID = T_SPFLI-CARRID
          AND CONNID = T_SPFLI-CONNID
          AND FLDATE BETWEEN '19990101' AND '19990331'.
    ENDSELECT.
    The above mentioned code can be even more optimized by using subqueries instead of for all entries.
    SELECT * FROM SFLIGHT AS F INTO SFLIGHT_WA
        WHERE SEATSOCC < F~SEATSMAX
          AND EXISTS ( SELECT * FROM SPFLI
                         WHERE CARRID = F~CARRID
                           AND CONNID = F~CONNID
                           AND CITYFROM = 'FRANKFURT'
                           AND CITYTO = 'NEW YORK' )
          AND FLDATE BETWEEN '19990101' AND '19990331'.
    ENDSELECT.
    <b>Internal Tables</b>
    1.     Table operations should be done using explicit work areas rather than via header lines.
    2.     Always try to use binary search instead of linear search. But don’t forget to sort your internal table before that.
    3.     A dynamic key access is slower than a static one, since the key specification must be evaluated at runtime.
    4.     A binary search using secondary index takes considerably less time.
    5.     LOOP ... WHERE is faster than LOOP/CHECK because LOOP ... WHERE evaluates the specified condition internally.
    6.     Modifying selected components using “ MODIFY itab …TRANSPORTING f1 f2.. “ accelerates the task of updating  a line of an internal table.
    Point # 2
    READ TABLE ITAB INTO WA WITH KEY K = 'X‘ BINARY SEARCH.
    IS MUCH FASTER THAN USING
    READ TABLE ITAB INTO WA WITH KEY K = 'X'.
    If TAB has n entries, linear search runs in O( n ) time, whereas binary search takes only O( log2( n ) ).
    Point # 3
    READ TABLE ITAB INTO WA WITH KEY K = 'X'. IS FASTER THAN USING
    READ TABLE ITAB INTO WA WITH KEY (NAME) = 'X'.
    Point # 5
    LOOP AT ITAB INTO WA WHERE K = 'X'.
    ENDLOOP.
    The above code is much faster than using
    LOOP AT ITAB INTO WA.
      CHECK WA-K = 'X'.
    ENDLOOP.
    Point # 6
    WA-DATE = SY-DATUM.
    MODIFY ITAB FROM WA INDEX 1 TRANSPORTING DATE.
    The above code is more optimized as compared to
    WA-DATE = SY-DATUM.
    MODIFY ITAB FROM WA INDEX 1.
    7.     Accessing the table entries directly in a "LOOP ... ASSIGNING ..." accelerates the task of updating a set of lines of an internal table considerably
    8.    If collect semantics is required, it is always better to use to COLLECT rather than READ BINARY and then ADD.
    9.    "APPEND LINES OF itab1 TO itab2" accelerates the task of appending a table to another table considerably as compared to “ LOOP-APPEND-ENDLOOP.”
    10.   “DELETE ADJACENT DUPLICATES“ accelerates the task of deleting duplicate entries considerably as compared to “ READ-LOOP-DELETE-ENDLOOP”.
    11.   "DELETE itab FROM ... TO ..." accelerates the task of deleting a sequence of lines considerably as compared to “  DO -DELETE-ENDDO”.
    Point # 7
    Modifying selected components only makes the program faster as compared to Modifying all lines completely.
    e.g,
    LOOP AT ITAB ASSIGNING <WA>.
      I = SY-TABIX MOD 2.
      IF I = 0.
        <WA>-FLAG = 'X'.
      ENDIF.
    ENDLOOP.
    The above code works faster as compared to
    LOOP AT ITAB INTO WA.
      I = SY-TABIX MOD 2.
      IF I = 0.
        WA-FLAG = 'X'.
        MODIFY ITAB FROM WA.
      ENDIF.
    ENDLOOP.
    Point # 8
    LOOP AT ITAB1 INTO WA1.
      READ TABLE ITAB2 INTO WA2 WITH KEY K = WA1-K BINARY SEARCH.
      IF SY-SUBRC = 0.
        ADD: WA1-VAL1 TO WA2-VAL1,
             WA1-VAL2 TO WA2-VAL2.
        MODIFY ITAB2 FROM WA2 INDEX SY-TABIX TRANSPORTING VAL1 VAL2.
      ELSE.
        INSERT WA1 INTO ITAB2 INDEX SY-TABIX.
      ENDIF.
    ENDLOOP.
    The above code uses BINARY SEARCH for collect semantics. READ BINARY runs in O( log2(n) ) time. The above piece of code can be more optimized by
    LOOP AT ITAB1 INTO WA.
      COLLECT WA INTO ITAB2.
    ENDLOOP.
    SORT ITAB2 BY K.
    COLLECT, however, uses a hash algorithm and is therefore independent
    of the number of entries (i.e. O(1)) .
    Point # 9
    APPEND LINES OF ITAB1 TO ITAB2.
    This is more optimized as compared to
    LOOP AT ITAB1 INTO WA.
      APPEND WA TO ITAB2.
    ENDLOOP.
    Point # 10
    DELETE ADJACENT DUPLICATES FROM ITAB COMPARING K.
    This is much more optimized as compared to
    READ TABLE ITAB INDEX 1 INTO PREV_LINE.
    LOOP AT ITAB FROM 2 INTO WA.
      IF WA = PREV_LINE.
        DELETE ITAB.
      ELSE.
        PREV_LINE = WA.
      ENDIF.
    ENDLOOP.
    Point # 11
    DELETE ITAB FROM 450 TO 550.
    This is much more optimized as compared to
    DO 101 TIMES.
      DELETE ITAB INDEX 450.
    ENDDO.
    12.   Copying internal tables by using “ITAB2[ ] = ITAB1[ ]” as compared to “LOOP-APPEND-ENDLOOP”.
    13.   Specify the sort key as restrictively as possible to run the program faster.
    Point # 12
    ITAB2[] = ITAB1[].
    This is much more optimized as compared to
    REFRESH ITAB2.
    LOOP AT ITAB1 INTO WA.
      APPEND WA TO ITAB2.
    ENDLOOP.
    Point # 13
    “SORT ITAB BY K.” makes the program runs faster as compared to “SORT ITAB.”
    Internal Tables         contd…
    Hashed and Sorted tables
    1.     For single read access hashed tables are more optimized as compared to sorted tables.
    2.      For partial sequential access sorted tables are more optimized as compared to hashed tables
    Hashed And Sorted Tables
    Point # 1
    Consider the following example where HTAB is a hashed table and STAB is a sorted table
    DO 250 TIMES.
      N = 4 * SY-INDEX.
      READ TABLE HTAB INTO WA WITH TABLE KEY K = N.
      IF SY-SUBRC = 0.
      ENDIF.
    ENDDO.
    This runs faster for single read access as compared to the following same code for sorted table
    DO 250 TIMES.
      N = 4 * SY-INDEX.
      READ TABLE STAB INTO WA WITH TABLE KEY K = N.
      IF SY-SUBRC = 0.
      ENDIF.
    ENDDO.
    Point # 2
    Similarly for Partial Sequential access the STAB runs faster as compared to HTAB
    LOOP AT STAB INTO WA WHERE K = SUBKEY.
    ENDLOOP.
    This runs faster as compared to
    LOOP AT HTAB INTO WA WHERE K = SUBKEY.
    ENDLOOP.
    <b>Reward if usefufll</b>

  • Partition pruning, Nested loops

    Hi,
    I am having a problem with getting partition pruning in a query. I've managed to dumb down the problem to two tables and a minimal query (see below).
    Basically, I have a partitioned table "Yearly Facts", and a helper table "Current Year" that always contain 1 row. The sole purpose of this one row is to tell what the curent year is, what the previous year was and what the next year will be. (In the real problem, there are non-standard timeperiods, so one cannot just calculate previous and next by adding/subtracting 1 as would be possible in this example).
    The following query is executed the way I want.
    It performs a scan on current_year, and then nested loop into the facts. And partition pruning was happening.
    select sum(decode(a.year_key, b.curr_year, some_measure)) as curr_year_measure
      from yearly_fact_t a
          ,current_year  b
    where a.year_key = b.curr_year;
    | Id  | Operation                  | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT           |               |     1 |    39 |     4   (0)| 00:00:01 |       |    |
    |   1 |  SORT AGGREGATE            |               |     1 |    39 |            |          |       |    |
    |   2 |   NESTED LOOPS             |               |     1 |    39 |     4   (0)| 00:00:01 |       |    |
    |   3 |    INDEX FAST FULL SCAN    | SYS_C00247890 |     1 |    13 |     2   (0)| 00:00:01 |       |    |
    |   4 |    PARTITION RANGE ITERATOR|               |     1 |    26 |     2   (0)| 00:00:01 |   KEY |   KEY |
    |*  5 |     TABLE ACCESS FULL      | YEARLY_FACT_T |     1 |    26 |     2   (0)| 00:00:01 |   KEY |   KEY |
    Predicate Information (identified by operation id):
       5 - filter("A"."YEAR_KEY"="B"."CURR_YEAR")The following query is where I have my problem.
    The basic xplan is the same, but for some reason the cbo gave up and decide to scan all partitions, which was not very scalable on production data :)
    I would have thought that the plan would be the same.
    select sum(decode(a.year_key, b.curr_year, some_measure)) as curr_year_measure
          ,sum(decode(a.year_key, b.prev_year, some_measure)) as prev_year_measure
      from yearly_fact_t a
          ,current_year  b
    where a.year_key = b.curr_year
        or a.year_key = b.prev_year;
    | Id  | Operation             | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT      |               |     1 |    52 |    13   (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE       |               |     1 |    52 |            |          |       |       |
    |   2 |   NESTED LOOPS        |               |     4 |   208 |    13   (0)| 00:00:01 |       |       |
    |   3 |    TABLE ACCESS FULL  | CURRENT_YEAR  |     1 |    26 |     4   (0)| 00:00:01 |       |       |
    |   4 |    PARTITION RANGE ALL|               |     4 |   104 |     9   (0)| 00:00:01 |     1 |     6 |
    |*  5 |     TABLE ACCESS FULL | YEARLY_FACT_T |     4 |   104 |     9   (0)| 00:00:01 |     1 |     6 |
    Predicate Information (identified by operation id):
       5 - filter("A"."YEAR_KEY"="B"."CURR_YEAR" OR "A"."YEAR_KEY"="B"."PREV_YEAR")
    -- drop table yearly_fact_t purge;
    -- drop table current_year  purge;
    create table current_year(
       curr_year number(4) not null
      ,prev_year number(4) not null
      ,next_year number(4) not null
      ,primary key(curr_year)
      ,unique(prev_year)
      ,unique(next_year)
    insert into current_year(curr_year, prev_year, next_year) values(2010, 2009, 2011);
    commit;
    create table yearly_fact_t(
       year_key     number(4) not null
      ,some_dim_key number    not null
      ,some_measure number    not null
    partition by range(year_key)(
       partition p2007 values less than(2008)
      ,partition p2008 values less than(2009)
      ,partition p2009 values less than(2010)
      ,partition p2010 values less than(2011)
      ,partition p2011 values less than(2012) 
      ,partition pmax  values less than(maxvalue)
    insert into yearly_fact_t(year_key, some_dim_key, some_measure) values(2007,1, 10);
    insert into yearly_fact_t(year_key, some_dim_key, some_measure) values(2008,1, 20);
    insert into yearly_fact_t(year_key, some_dim_key, some_measure) values(2009,1, 30);
    insert into yearly_fact_t(year_key, some_dim_key, some_measure) values(2010,1, 40);
    commit; What can I do to get partition pruning to happen in the second query?
    Or even better, what is it in my query that prevents it from happening?
    We're running Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit.
    Best regards
    Ronnie

    Hi Ronnie,
    Check whether your statistics are up to date.
    SQL> set autotrace traceonly exp
    SQL> select sum(decode(a.year_key, b.curr_year, some_measure)) as curr_year_measure
      2        ,sum(decode(a.year_key, b.prev_year, some_measure)) as prev_year_measure
      3    from yearly_fact_t a
      4        ,current_year  b
      5   where a.year_key = b.curr_year
      6      or a.year_key = b.prev_year;
    Execution Plan
    Plan hash value: 229094315
    | Id  | Operation             | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT      |               |     1 |    52 |    10   (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE       |               |     1 |    52 |            |          |       |       |
    |   2 |   NESTED LOOPS        |               |     4 |   208 |    10   (0)| 00:00:01 |       |       |
    |   3 |    TABLE ACCESS FULL  | CURRENT_YEAR  |     1 |    26 |     3   (0)| 00:00:01 |       |       |
    |   4 |    PARTITION RANGE ALL|               |     4 |   104 |     7   (0)| 00:00:01 |     1 |     6 |
    |*  5 |     TABLE ACCESS FULL | YEARLY_FACT_T |     4 |   104 |     7   (0)| 00:00:01 |     1 |     6 |
    Predicate Information (identified by operation id):
       5 - filter("A"."YEAR_KEY"="B"."CURR_YEAR" OR "A"."YEAR_KEY"="B"."PREV_YEAR")
    Note
       - dynamic sampling used for this statement
    SQL> set autotrace off
    SQL> exec dbms_stats.gather_table_stats(user, 'current_year', estimate_percent=>100, cascade=>true, method_opt
    =>'for all columns size 1');
    PL/SQL procedure successfully completed.
    SQL>
    SQL> exec dbms_stats.gather_table_stats(user, 'yearly_fact_t', estimate_percent=>100, cascade=>true, method_op
    t=>'for all columns size 1');
    PL/SQL procedure successfully completed.
    SQL> set autotrace traceonly exp
    SQL> select sum(decode(a.year_key, b.curr_year, some_measure)) as curr_year_measure
      2        ,sum(decode(a.year_key, b.prev_year, some_measure)) as prev_year_measure
      3    from yearly_fact_t a
      4        ,current_year  b
      5   where a.year_key = b.curr_year
      6      or a.year_key = b.prev_year;
    Execution Plan
    Plan hash value: 2253546831
    | Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    |   0 | SELECT STATEMENT            |               |     1 |    15 |     8   (0)| 00:00:01 |       |       |
    |   1 |  SORT AGGREGATE             |               |     1 |    15 |            |          |       |       |
    |   2 |   CONCATENATION             |               |       |       |            |          |       |       |
    |   3 |    NESTED LOOPS             |               |     1 |    15 |     4   (0)| 00:00:01 |       |       |
    |   4 |     TABLE ACCESS FULL       | CURRENT_YEAR  |     1 |     8 |     3   (0)| 00:00:01 |       |       |
    |   5 |     PARTITION RANGE ITERATOR|               |     1 |     7 |     1   (0)| 00:00:01 |   KEY |   KEY |
    |*  6 |      TABLE ACCESS FULL      | YEARLY_FACT_T |     1 |     7 |     1   (0)| 00:00:01 |   KEY |   KEY |
    |   7 |    NESTED LOOPS             |               |     1 |    15 |     4   (0)| 00:00:01 |       |       |
    |   8 |     TABLE ACCESS FULL       | CURRENT_YEAR  |     1 |     8 |     3   (0)| 00:00:01 |       |       |
    |   9 |     PARTITION RANGE ITERATOR|               |     1 |     7 |     1   (0)| 00:00:01 |   KEY |   KEY |
    |* 10 |      TABLE ACCESS FULL      | YEARLY_FACT_T |     1 |     7 |     1   (0)| 00:00:01 |   KEY |   KEY |
    Predicate Information (identified by operation id):
       6 - filter("A"."YEAR_KEY"="B"."PREV_YEAR")
      10 - filter("A"."YEAR_KEY"="B"."CURR_YEAR" AND LNNVL("A"."YEAR_KEY"="B"."PREV_YEAR"))
    SQL> set autotrace off
    SQL>Asif Momen
    http://momendba.blogspot.com

  • Nested loop join v/s Sort merge

    I have seen that nested loops are better if the inner table is being indexed, because for each outer table row, we are looking for a match in the inner table. But is there any case when optimizer still goes for a nested loop even if there is no index on the inner table. That is my first question ?
    My second question := When doing a sort merge join oracle has to sort both result sets and then merge them. Oracle says that if both the row sets, if already sorted is definately better for performance. Ya thats obvious. But back to my upper question, when there is no index on the inner table, is it the situation when oracle goes for a sort merge join ?

    My response should really have examples but since I do not have any handy I will just say about your first question. If there is no index available from table A to table B yes it is possible a nested loop join may still be used and table B read via full table scan within a nested loop. If table B is very small and consists of only a block or two this may be relatively efficient plan. It is more likely you sould see table B full scanned and the result feed into a hash join, but I have seen the plan you mention.
    Back before hash joins were introduced with 7.3 (if my memory is correct) you would see sort/merge joins used more often than you do now. Generally speaking no index on the join conditions would exist for this option to be chosen.
    If you really want to know why and sometimes what the optimizer is going to do buy Jonathan Lewis's book Cost-Based Oracle Fundamentals. If explains the optimizer in more depth than any other source I know of.
    HTH -- Mark D Powell --

  • Nested Loop Help

    Hello,
    I have generated a simple VI, to make multiplication and division operations. I have the following operation performed with the following inputs.
    A1 has a value range from 1 -10 fixed
    A2 has an input range of 1 - 5
    A3,A4 are constants.
    so Result  = (A1*A3 ) / (A4*A2)*100 ,
    I want to  plot "Result Vs. A1" with a current value of A2, increment A2 and repeat the procedure. So I generate 5 graphs and display it in only one. I need to write a nested loop to perform this operation.however I am able to do it only once.
    I am trying to use for loop structure in one another but havent gone ahead in this.Any help will be appreciable..Thanks in advance.

    altenbach wrote:
    Dravi99 wrote:
    The Problem is that I want to plot the division result vs. the # of array out elements and i am unsuccessful at it. May be i am missing on the waveform graph properties.
    You should make the current values default before saving so we have some typical data to play with.
    Currently, your code makes very little sense, because the inner loop has no purpose.
    If you plot the division result versus array index (I assume that's what you want, I don't understand what you mean by "the # of array out elements "), you only have one plot. What should be on the other plots???
    Please explain or even attach an image of the desired output. Thanks!
    Thanks Altenbach for the inputs.
    I have made the values default. Srry for the previous one.
    Now the inner loop was placed so that i can create a 2D array.
    I need to plot the division result vs. the value of the element in the arry out. i.e. currently my array out has 0.0...,0.3 I want that to be the X axis.
     The graph plotted   is for 1st value of "in", this value will change like from 4.5 to 4.7 to 4.9, not necesarily in steps.
    Thus my one graph should have multiple plots of "in" which has the above mentioned axis.
    Hope this time i was clear in my msg. I have attached the modified VI.
    Attachments:
    For_loop_prob.vi ‏17 KB

  • CBO (optimizer) nest-loop join question

    OS: Red Hat Linux
    DB: 11gR1
    I have gotten two conflicting answers while reading books by Don Burleson and Dan Hotka. It has to do with the CBO and nested-joins:
    One says the CBO will choose the 'smaller' table as the driving table, the other states that the 'larger' table will be the driving table. And both stick by this philosophy as the preferred goal of any SQL Tuning -- that is, one states that the 'smaller' table should be the driving table. The other says the 'larger' table should be the driving table.
    I had always thought that the 'smaller' table should be the driving table. That in a nested loop the driving will not likely use an index even. Who is correct? (I am not going to say who said what, btw). :-)
    But I got to let one of them know they got a 'typo' ... :-)
    Thx.

    user601798 wrote:
    It is an over-simplistic scenario but, as I mentioned, if all other things are 'equal' -- which would include 'access time/work', then I think the small table as the driving table has the advantage.
    It is not possible for +"*all* other things to be equal"+. (my emphasis).
    If by +'access time/work'+ you mean the total is the same then it doesn't matter which table is first, the time/work is the same either way round.
    If you want to say that the +'access time/work'+ for acquiring the first rowsource is the same for both paths, and the +'access time/work'+ for acquiring related rows from the second table is the same FOR EACH DRIVING ROW, then the total +'access time/work'+ will be difference, and it would be better to start with the smaller table. (The example by Salman Qureshi above: Re: CBO (optimizer) nest-loop join question would apply.)
    On the other hand, and ignoring any idea of "all other things being equal", smaller tables tend to have smaller indexes, so if your smaller rowsource comes from a smaller table then acquiring those rows may be cheaper than acquiring rows from a larger table - which leads to the observation that (even with perfectly precise indexing):
    <ul>
    smaller number of rows * larger unit cost to find related rows
    </ul>
    may produce a larger value than
    <ul>
    larger number of rows * smaller unit cost to find related rows
    </ul>
    Regards
    Jonathan Lewis
    http://jonathanlewis.wordpress.com
    http://www.jlcomp.demon.co.uk
    A general reminder about "Forum Etiquette / Reward Points": http://forums.oracle.com/forums/ann.jspa?annID=718
    If you never mark your questions as answered people will eventually decide that it's not worth trying to answer you because they will never know whether or not their answer has been of any use, or whether you even bothered to read it.
    It is also important to mark answers that you thought helpful - again it lets other people know that you appreciate their help, but it also acts as a pointer for other people when they are researching the same question, moreover it means that when you mark a bad or wrong answer as helpful someone may be prompted to tell you (and the rest of the forum) what's so bad or wrong about the answer you found helpful.

  • Is merge join cartesian more cpu intensibe than nested loop ?

    Hi,
    just wonderning which access method is more cpu intensive , lets supposed we got 2 the same row sources and doing joing via merge join cartesian and next case is nested loop .
    I know NL can be cpu intensive because of tight loop access , but what abour MJC ?
    I can see bufferd sort but not sure is that cpu friendly ?
    Regards
    GregG

    Hi,
    I think in your case it's more accurate to compare a NESTED LOOP (NL) to a MERGE JOIN (MJ), because CARTESIAN MERGE JOIN is a rather special case of MJ.
    Merge join sorts its inputs before combining them, and it could be efficient when one or both of inputs are already sorted.
    Regarding your question (which is more CPU intensive):
    1) if MERGE JOIN involves disk spills, then CPU is probably irrelevant, because disk operations are much more expensive
    2) the amount of work to combine rowsources via a MJ depends on how well they are aligned with respect to each other, so I don't think it can be expressed via a simple formula.
    For nested loops, the situation is much more simple: you don't need to do any special work do combine the rowsource, so the cost is just the sum of the cost acquiring the outer rowsource plus the number of iterations times the cost of one iteration. If the data is read from disk, then CPU probably won't matter much, if most of reads are logical ones than CPU becomes of a factor (it's hard to tell how much work CPU will have to do per one logical read because there are two many factors here -- how many columns are accessed, how they are located within the block, are there any expensive math functions applied to any of them etc.)
    Best regards,
    Nikolay

  • How to disable nested loop option on a 10gR2 OLAP environment?

    is it possible to disable nested loop option on a 10gR2 OLAP environment? There are some thousands of automatically generated report queries and whenever a join is needed we want to force hash join if possible(equality) or sort merge but never nested loop. optimizer sometimes can go for NL because of broken ETL, last steps as collecting statistics can not be finished successfully before the users start to do their reporting.
    of course looking for a global parameter and do not want to hint each and every possible report query :)
    thank you.

    In general, connections that use a thin (type 4) JDBC driver will bypass the tnsnames.ora and sqlnet.ora files because they don't need those files to exist. One of the primary benefit of the type 4 JDBC drivers is that the Java code's connection string is fully specified in Java and doesn't depend on configuration files outside the JVM. So I wouldn't be surprised that any Java-based application could use the EZConnect syntax.
    It is not obvious to me, though, why EZConnect would bypass any SSL tunnel that you had established. Assuming that you've instructed your client to send all traffic on a particular port going to a particular IP address to use a tunnel, I'm not sure why (or how) EZConnect syntax would bypass that. I would tend to expect that the problem was with the SSL tunnel configuration but perhaps I'm missing something on the network side.
    Justin

  • XML Publisher Multiple loops page break

    In my XML Publisher template i am haveing nested loops. The tag <?split-by-page-break:?> is working fine for all but the last iteration. Is there a tag for page break which work always irrespective of the iteration.
    I cannot use ctrl+enter in the template as the whole page is a table whose headers are repeating and on inserting the ctrl+enter the table break.
    Is there any other way to achieve the functionality of ctrl+enter through the xml tag.

    Hi,
    Yes, i was abe to do this, i moved the Customer name filed above the Invoice group and added extra conditin in the rtf.
    Regards,
    RR

  • Collecting data from nested loops

    I have ended up with a program having "case" loop at the top level and 3-4 nested "for" and "while" loops. Now from the inner most loop from each "case", I want to pull out the data, fromat it and then write it in a excel sheet. The problem is that I am not able to pull out the data. Everytime I try to do it, the dimension of array changes due to the nested loops. Is there a better way to do it?
    Thanks,
    Vivek

    It is not possible for us to troubleshoot the code from an image that only show part of it.
    From what I can see, a lot of things don't make much sense. Also please don't run wires backwards (such as the wires from the "How many channels" Control entering the big loop from the right.) This can make reading and debugging a diagram very difficult!
    Let's look at the inner FOR loop on the right: It runs several times, generating 1D arrays each time.
    Leaving this loop, they autoindex into 2d arrays, whitch you reshape into 1D arrays.
    Leaving the next loop some are autoindexed into another 2D array, except for the top one, where you only retain the data from the last iteration. Is that really what you want?
    Now we exit a case strucure, where apparently each case has it's own three outputs, so for each case, One set contains data, but the other two sets generate empty data. About 2/3 of all your data is zero, this is a lot of wasted memory!
    Leaving the big FOR loop, nothing is indexed, meaning you only get sets of 1D and 2D arrays from the last iteration. If you would autoindex, you would get 2D and 3D arrays.
    As you can see, this all make little sense unless we can see the code and some real data. Also, you have not implemented any of my suggestions from above. Why not?
    Message Edited by altenbach on 07-21-2005 08:37 AM
    LabVIEW Champion . Do more with less code and in less time .

  • Help tuning NESTED LOOPS OUTER joins

    Hello,
    I have inherited this nasty query (below) that is taking an awful time to complete (more than 2 hrs a day)
    The worst bit is that I need to outer join my fact table so many times as I need bit’s and pieces from other tables/mviews.
    When I look at the explain plan I see that this situation means that the cbo is doing several NESTED LOOPS OUTER join operations. I understand that these nested loops mean going through every row in my primary table to see if there is a match in the secondary table (much smaller) which makes it extremely inefficient, is this right?
    The stats on the tables are all refreshed daily.
    Any ideas on how I can improve the performance here?
    Thanks in advance!
    The query:
    explain plan for
    SELECT x.user_id AS user_id,
    x.login_name AS login_name,
    c.date_of_birth AS date_of_birth,
    x.registration_site AS registration_site,
    x.organisation AS organisation,
    c.user_title AS user_title,
    c.first_name AS first_name,
    c.last_name AS last_name,
    x.email_address AS email_address,
    x.user_status AS user_status,
    x.user_privilege AS user_access_privilege,
    x.date_registration AS date_registration,
    x.affiliate_id AS affiliate_id,
    x.mobile_number AS mobile_number,
    x.optional_parameter AS vt_number,
    gud.display_name AS chat_name,
    REPLACE (s4.address_line_1, ',', '') AS address_line_1,
    REPLACE (s4.address_line_2, ',', '') AS address_line_2,
    REPLACE (s4.town, ',', '') AS town,
    REPLACE (s4.county, ',', '') AS county,
    REPLACE (s4.postcode, ',', '') AS postcode,
    s4.country AS country,
    s3.last_login AS last_login_date,
    x.email_send_newsletter AS email_send_newsletter,
    x.email_give_details_thirdparty AS email_give_details_thirdparty,
    NVL (ia.cash_balance, 0) AS current_cash_balance,
    NVL (ia.bonus_balance, 0) AS current_bonus_balance,
    x.external_affiliate_id AS external_affiliate_id,
    r.currency_code AS currency,
    NVL (ia.points_balance, 0) AS current_loyalty_points_balance,
    p.status AS buyer_status,
    NVL (ia.bi_bonus_balance, 0) AS current_bi_bonus_balance,
    NVL (ia.pending_balance, 0) AS current_pending_balance,
    l.level_name AS current_loyalty_level,
    l.date_level_achieved AS date_level_achieved,
    NVL (l.current_period_loyalty_points, 0) AS current_period_loyalty_points,
    r.region AS user_region,
    x.registration_platform AS registration_platform,
    x.external_user_name AS external_user_name,
    c.home_number AS home_number,
    pr.code AS reg_promo_code,
    g.date_first_buy AS date_first_buy
    FROM gl_user_registrations x,
    gl_region r,
    MVW_USER_BALANCES ia,
    gl_customers c,
    gl_user_display_names gud,
    gl_user_last_login s3,
    (SELECT z.user_id AS user_id,
    z.address_line_1 AS address_line_1,
    z.address_line_2 AS address_line_2,
    z.town AS town,
    z.county AS county,
    z.postcode AS postcode,
    z.country AS country
    FROM gl_user_addresses z
    WHERE z.is_current = 1) s4,
    gl_user_buyer_mapping upm,
    gl_buyer p,
    mvw_user_loyalty_points l,
    MVW_USER_PROMO_CODE_REG pr,
    MVW_USER_FIRST_BUY_DATE g
    WHERE x.base_region = r.region
    AND x.user_id = ia.user_id (+)
    AND x.customer_id = c.customer_id(+)
    AND x.user_id = gud.user_id (+)
    AND x.user_id = s4.user_id (+)
    AND x.user_id = s3.user_id (+)
    AND x.user_id = upm.user_id (+)
    AND upm.buyer_id = p.buyer_id
    AND x.user_id = l.user_id (+)
    AND x.user_id = pr.user_id (+)
    AND x.user_id = g.user_id (+);
    select * from table(dbms_xplan.display);
    Plan hash value: 2158171613
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    | 0 | SELECT STATEMENT | | 100 | 63100 | 135 (1)| 00:00:01 |
    | 1 | NESTED LOOPS OUTER | | 100 | 63100 | 135 (1)| 00:00:01 |
    | 2 | NESTED LOOPS OUTER | | 100 | 60600 | 120 (1)| 00:00:01 |
    | 3 | NESTED LOOPS OUTER | | 100 | 57100 | 105 (1)| 00:00:01 |
    | 4 | NESTED LOOPS OUTER | | 100 | 55400 | 90 (2)| 00:00:01 |
    | 5 | NESTED LOOPS OUTER | | 100 | 53600 | 70 (2)| 00:00:01 |
    |* 6 | HASH JOIN | | 100 | 47000 | 55 (2)| 00:00:01 |
    | 7 | TABLE ACCESS FULL | GL_REGION | 18 | 252 | 2 (0)| 00:00:01 |
    | 8 | NESTED LOOPS OUTER | | 100 | 22800 | 52 (0)| 00:00:01 |
    | 9 | NESTED LOOPS OUTER | | 100 | 19700 | 47 (0)| 00:00:01 |
    | 10 | NESTED LOOPS OUTER | | 100 | 17600 | 37 (0)| 00:00:01 |
    | 11 | NESTED LOOPS | | 100 | 15800 | 27 (0)| 00:00:01 |
    | 12 | NESTED LOOPS | | 102 | 2754 | 17 (0)| 00:00:01 |
    | 13 | TABLE ACCESS FULL | GL_BUYER | 6143K| 64M| 2 (0)| 00:00:01 |
    | 14 | TABLE ACCESS BY INDEX ROWID| GL_USER_BUYER_MAPPING | 1 | 16 | 1 (0)| 00:00:01 |
    |* 15 | INDEX RANGE SCAN | GL_USER_BUYER_MAPPPING_IX | 1 | | 1 (0)| 00:00:01 |
    | 16 | TABLE ACCESS BY INDEX ROWID | GL_USER_REGISTRATIONS | 1 | 131 | 1 (0)| 00:00:01 |
    |* 17 | INDEX UNIQUE SCAN | PK_GL_USER_REGISTRATIONS | 1 | | 1 (0)| 00:00:01 |
    | 18 | TABLE ACCESS BY INDEX ROWID | GL_USER_LAST_LOGIN | 1 | 18 | 1 (0)| 00:00:01 |
    |* 19 | INDEX UNIQUE SCAN | GL_USER_LAST_LOGIN_PK | 1 | | 1 (0)| 00:00:01 |
    | 20 | TABLE ACCESS BY INDEX ROWID | GL_USER_DISPLAY_NAMES | 1 | 21 | 1 (0)| 00:00:01 |
    |* 21 | INDEX UNIQUE SCAN | PK_GL_USER_DISPLAY_NAMES | 1 | | 1 (0)| 00:00:01 |
    | 22 | TABLE ACCESS BY INDEX ROWID | GL_CUSTOMERS | 1 | 31 | 1 (0)| 00:00:01 |
    |* 23 | INDEX UNIQUE SCAN | PK_GL_CUSTOMERS | 1 | | 1 (0)| 00:00:01 |
    |* 24 | TABLE ACCESS BY INDEX ROWID | GL_USER_ADDRESSES | 1 | 66 | 1 (0)| 00:00:01 |
    |* 25 | INDEX RANGE SCAN | IX_GL_USER_ADDRESSES1 | 1 | | 1 (0)| 00:00:01 |
    | 26 | MAT_VIEW ACCESS BY INDEX ROWID | MVW_USER_FIRST_BUY_DATE | 1 | 18 | 1 (0)| 00:00:01 |
    |* 27 | INDEX RANGE SCAN | MVW_USER_FS_DATE_IDX | 1 | | 1 (0)| 00:00:01 |
    | 28 | MAT_VIEW ACCESS BY INDEX ROWID | MVW_USER_PROMO_CODE_REG | 1 | 17 | 1 (0)| 00:00:01 |
    |* 29 | INDEX RANGE SCAN | MVW_USER_PROMO_CODE_IDX | 1 | | 1 (0)| 00:00:01 |
    | 30 | MAT_VIEW ACCESS BY INDEX ROWID | MVW_USER_LOYALTY_POINTS | 1 | 35 | 1 (0)| 00:00:01 |
    |* 31 | INDEX RANGE SCAN | MVW_USER_LYP_IDX | 1 | | 1 (0)| 00:00:01 |
    | 32 | MAT_VIEW ACCESS BY INDEX ROWID | MVW_USER_BALANCES | 1 | 25 | 1 (0)| 00:00:01 |
    |* 33 | INDEX RANGE SCAN | MVW_USER_BALANCES_IDX | 1 | | 1 (0)| 00:00:01 |
    Predicate Information (identified by operation id):
    6 - access("X"."BASE_REGION"="R"."REGION")
    15 - access("UPM"."BUYER_ID"="P"."BUYER_ID")
    17 - access("X"."USER_ID"="UPM"."USER_ID")
    19 - access("X"."USER_ID"="S3"."USER_ID"(+))
    21 - access("X"."USER_ID"="GUD"."USER_ID"(+))
    23 - access("X"."CUSTOMER_ID"="C"."CUSTOMER_ID"(+))
    24 - filter("Z"."IS_CURRENT"(+)=1)
    25 - access("X"."USER_ID"="Z"."USER_ID"(+))
    27 - access("X"."USER_ID"="G"."USER_ID"(+))
    29 - access("X"."USER_ID"="PR"."USER_ID"(+))
    31 - access("X"."USER_ID"="L"."USER_ID"(+))
    33 - access("X"."USER_ID"="IA"."USER_ID"(+))

    Hi,
    1) What you are saying about nested loops is true about any join (except, of course, cartesian joins): you are taking rows from rowsource A and find matching rows from rowsource B. This doesn't make a join method efficient or inefficient.
    2) The plan you posted does not indicate any performance problem whatsoever. I know you have one, but it's not possible to address it without having any information about it. Trace it, get dbms_xplan.display_cursor dump with rowsource stats, or real-time SQL monitoring report (if your version and license allow it) and post the results here, then we'd be able to help
    3) One efficient way to perform queries of your type (big fact table joined to a bunch of small dimension tables) is star transformation, but there are certain pre-requisites for that (like bitmap indexes on FK constraints) -- please read the documentation on star queries/transformations and see if that is an option for you
    Best regards,
    Nikolay

Maybe you are looking for