sql >> Database teknologi >  >> RDS >> Oracle

Langsom ydeevne for deeply nested subquery factoring (CTE)

Spørgsmål 1:Det ser ud til, at der ikke er noget om beregningstid, bare fejl i optimeringsalgoritmen, som gør det galt, mens man beregner en plan for den bedste udførelse.

Spørgsmål 2:Der er en række kendte og rettede fejl i Oracle 11.X.0.X relateret til optimering af indlejrede forespørgsler og query factoring. Men det er meget svært at finde et konkret problem.

Spørgsmål 3:Der er to udokumenterede tip:materialize og inline men ingen af ​​dem virker for mig, mens jeg prøvede dit eksempel. Det er muligt, at nogle ændringer i serverkonfigurationen eller opgradering til 11.2.0.3 kan øge grænsen for indlejret with klausuler:for mig (på 11.2.0.3 Win7/x86) fungerer dit eksempel fint, men et stigende antal indlejrede tabeller til 30 hænger en session.

Løsningen kan se sådan ud:

select k from (
select k, avg(k) over (partition by null) k_avg from ( --t16
  select k, avg(k) over (partition by null) k_avg from ( --t15
    select k, avg(k) over (partition by null) k_avg from ( --t14
      select k, avg(k) over (partition by null) k_avg from ( --t13
        select k, avg(k) over (partition by null) k_avg from ( --t12
          select k, avg(k) over (partition by null) k_avg from ( --t11
            select k, avg(k) over (partition by null) k_avg from ( --t10
              select k, avg(k) over (partition by null) k_avg from ( --t9
                select k, avg(k) over (partition by null) k_avg from ( --t8
                  select k, avg(k) over (partition by null) k_avg from ( --t7
                    select k, avg(k) over (partition by null) k_avg from ( --t6
                      select k, avg(k) over (partition by null) k_avg from ( --t5
                        select k, avg(k) over (partition by null) k_avg from ( --t4
                          select k, avg(k) over (partition by null) k_avg from ( --t3
                            select k, avg(k) over (partition by null) k_avg from ( --t2
                              select k, avg(k) over (partition by null) k_avg from ( -- t1
                                select k, avg(k) over (partition by null) k_avg from (select 0 as k from dual) t0
                              ) where k >= k_avg
                            ) where k >= k_avg
                          ) where k >= k_avg
                        ) where k >= k_avg
                      ) where k >= k_avg
                    ) where k >= k_avg
                  ) where k >= k_avg
                ) where k >= k_avg
              ) where k >= k_avg
            ) where k >= k_avg
          ) where k >= k_avg
        ) where k >= k_avg
      ) where k >= k_avg
    ) where k >= k_avg
  ) where k >= k_avg
) where k >= k_avg
)

Det virker i det mindste for mig på nesting-niveau på 30 og producerer en helt anden eksekveringsplan med WINDOW BUFFER og VIEW i stedet for LOAD TABLE AS SELECT , SORT AGGREGATE og TABLE ACCESS FULL .

Opdater

  1. Har lige installeret 11.2.0.4 (Win7/32bit) og test det mod den første forespørgsel. Intet ændret i optimeringsadfærd.

  2. Der er ingen mulighed for direkte at påvirke en CBO-adfærd, selv med brug af inline (udokumenteret) eller RULE (forældede) hints. Måske en guru kender en variant, men det er en tophemmelighed for mig (og Google også :-) .

  3. At gøre ting i en one select-sætning inden for rimelig tid er muligt, hvis en hovedselektionssætning er adskilt i dele og placeret i funktionen, som returnerer et sæt rækker (funktion, der returnerer sys_refcursor eller stærk indtastet cursor), men det er ikke et valg, hvis en forespørgsel konstrueret under kørsel.

  4. Løsning med brug af XML er mulig, men denne variant ligner at fjerne en tonsil gennem røvhullet (undskyld):

.

select
  extractvalue(column_value,'/t/somevalue') abc
from 
  table(xmlsequence((
    select t2 from (
      select
        t0,
        t1,
        (   
          select xmlagg(
                   xmlelement("t", 
                     xmlelement("k1",extractvalue(t1t.column_value,'/t/k1')), 
                     xmlelement("somevalue", systimestamp))
                  )
          from 
            table(xmlsequence(t0)) t0t, 
            table(xmlsequence(t1)) t1t  
          where 
            extractvalue(t1t.column_value,'/t/k1') >= (
              select avg(extractvalue(t1t.column_value, '/t/k1')) from table(xmlsequence(t1))
            )                                              
            and 
            extractvalue(t0t.column_value,'/t/k2') > 6
        ) t2
      from (
        select
          t0,
          (
            select xmlagg(
                     xmlelement("t", 
                       xmlelement("k1",extractvalue(column_value,'/t/k1')), 
                       xmlelement("somevalue", sysdate))
                    )
            from table(xmlsequence(t0))   
            where 
              extractvalue(column_value,'/t/k1') >= (
                select avg(extractvalue(column_value, '/t/k1')) from table(xmlsequence(t0))
              )
          ) t1
        from (
          select
            xmlagg(xmlelement("t", xmlelement("k1", level), xmlelement("k2", level + 3))) t0
          from dual connect by level < 5
        )
      )
    )
  )))

En anden ting ved en mærkelig kode ovenfor er, at denne variant kun gælder, hvis with datasæt havde ikke et stort antal rækker.



  1. Postgresql - ydeevne ved brug af array i stor database

  2. Django :mysql :1045, Adgang nægtet for bruger

  3. SQL Server 2008 Tom streng vs. plads

  4. tomcat 6.0.24 Undtagelse:Kunne ikke indlæse com.mysql.jdbc.SQLError