Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Performa lambat untuk subquery factoring (CTE) bersarang dalam

Q1:Sepertinya tidak ada apa-apa tentang waktu perhitungan, hanya bug dalam algoritma pengoptimal yang membuatnya gila saat menghitung rencana eksekusi terbaik.

Q2:Ada sejumlah bug yang diketahui dan diperbaiki di Oracle 11.X.0.X terkait dengan optimalisasi kueri bersarang dan pemfaktoran kueri. Tapi sangat sulit untuk menemukan masalah yang konkrit.

T3:Ada dua tidak berdokumen petunjuk:materialize dan inline tetapi tidak ada yang bekerja untuk saya ketika saya mencoba contoh Anda. Ada kemungkinan bahwa beberapa perubahan dalam konfigurasi server atau peningkatan ke 11.2.0.3 dapat meningkatkan batas with bersarang klausa:bagi saya (pada 11.2.0.3 Win7/x86) contoh Anda berfungsi dengan baik, tetapi peningkatan jumlah tabel bersarang menjadi 30 hang per sesi.

Solusinya mungkin terlihat seperti ini:

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
)

Setidaknya itu bekerja untuk saya pada level bersarang 30 dan menghasilkan rencana eksekusi yang sama sekali berbeda dengan WINDOW BUFFER dan VIEW alih-alih LOAD TABLE AS SELECT , SORT AGGREGATE dan TABLE ACCESS FULL .

Perbarui

  1. Baru saja menginstal 11.2.0.4 (Win7/32bit) dan mengujinya terhadap kueri awal. Tidak ada yang berubah dalam perilaku pengoptimal.

  2. Tidak ada kemungkinan untuk secara langsung memengaruhi perilaku CBO, bahkan dengan penggunaan inline (tidak berdokumen) atau RULE (usang) petunjuk. Mungkin beberapa Guru mengetahui beberapa varian, tapi itu Rahasia Utama bagi saya (dan Google juga :-) .

  3. Melakukan sesuatu dalam satu pernyataan pemilihan dalam waktu yang wajar dimungkinkan jika pernyataan pemilihan utama dipisahkan menjadi beberapa bagian dan ditempatkan ke dalam fungsi yang mengembalikan satu set baris (fungsi mengembalikan sys_refcursor atau kursor yang diketik kuat), tetapi itu bukan pilihan jika permintaan dibangun saat runtime.

  4. Pemecahan masalah dengan penggunaan XML dimungkinkan, tetapi varian ini terlihat seperti mengeluarkan amandel melalui lubang pantat (maaf):

.

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
        )
      )
    )
  )))

Hal lain tentang kode aneh di atas adalah varian ini hanya berlaku jika with kumpulan data tidak memiliki banyak baris.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cara Menginstal Pengembang SQL di Mac

  2. Membuat JSON dan mengedit kueri kompleks (Oracle 11g)

  3. Bagaimana cara menjatuhkan Oracle LOB

  4. Menginstal Oracle 12c Edisi Standar di Windows 10 Professional

  5. Membuat array asosiatif tingkat paket di java