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

cara untuk menghindari tabel temp global di Oracle

Mari kita jawab pertanyaan kedua terlebih dahulu:

"mengapa pergi dari GTT? apakah mereka benar-benar seburuk itu."

Beberapa hari yang lalu saya membuat bukti konsep yang memuat file XML besar (~ 18MB) ke dalam XMLType. Karena saya tidak ingin menyimpan XMLType secara permanen, saya mencoba memuatnya ke dalam variabel PL/SQL (memori sesi) dan tabel sementara. Memuatnya ke dalam tabel sementara membutuhkan waktu lima kali lebih lama daripada memuatnya ke dalam variabel XMLType (5 detik dibandingkan dengan 1 detik). Perbedaannya adalah karena tabel sementara bukanlah struktur memori:tabel tersebut ditulis ke disk (khususnya tablespace sementara yang Anda pilih).

Jika Anda ingin menyimpan banyak data, maka menyimpannya di memori akan membuat PGA stres, yang tidak baik jika Anda memiliki banyak sesi. Jadi ini adalah trade-off antara RAM dan waktu.

Untuk pertanyaan pertama:

"Dapatkah seseorang menunjukkan cara mengubah kueri sampel di atas menjadi koleksi dan/atau kursor?"

Kueri yang Anda posting dapat digabungkan menjadi satu pernyataan:

SELECT case when a.column_a IS NULL OR a.column_a = ' ' 
           then b.data_a
           else  column_a end AS someA,
       a.someB,
       a.someC
FROM TABLE_A a
      left outer join TABLE_B b
          on ( a.column_b = b.data_b AND a.column_c = 'C' )
WHERE condition_1 = 'YN756'
  AND type_cd = 'P'
  AND TO_NUMBER(TO_CHAR(m_date, 'MM')) = '12'
  AND (lname LIKE (v_LnameUpper || '%') OR
  lname LIKE (v_searchLnameLower || '%'))
  AND (e_flag = 'Y' OR
  it_flag = 'Y' OR
  fit_flag = 'Y'));

(Saya baru saja mengubah logika Anda tetapi case() pernyataan dapat diganti dengan nvl2(trim(a.column_a), a.column_a, b.data_a) yang lebih rapi ).

Saya tahu Anda mengatakan pertanyaan Anda lebih rumit, tetapi port panggilan pertama Anda harus mempertimbangkan untuk menulis ulang. Saya tahu betapa menggodanya memecah kueri kasar menjadi banyak SQL bayi yang digabungkan dengan PL/SQL tetapi SQL murni jauh lebih efisien.

Untuk menggunakan koleksi, yang terbaik adalah mendefinisikan tipe dalam SQL, karena memberikan kita fleksibilitas untuk menggunakannya dalam pernyataan SQL serta PL/SQL.

create or replace type tab_a_row as object
    (col_a number
     , col_b varchar2(23)
     , col_c date);
/
create or replace type tab_a_nt as table of tab_a_row;
/

Berikut adalah contoh fungsi, yang mengembalikan kumpulan hasil:

create or replace function get_table_a 
      (p_arg in number) 
      return sys_refcursor 
is 
    tab_a_recs tab_a_nt; 
    rv sys_refcursor; 
begin 
    select tab_a_row(col_a, col_b, col_c)  
    bulk collect into tab_a_recs 
    from table_a 
    where col_a = p_arg; 

    for i in tab_a_recs.first()..tab_a_recs.last() 
    loop 
        if tab_a_recs(i).col_b is null 
        then 
            tab_a_recs(i).col_b :=  'something'; 
        end if; 
    end loop;  

    open rv for select * from table(tab_a_recs); 
    return rv; 
end; 
/ 

Dan inilah aksinya:

SQL> select * from table_a
  2  /

     COL_A COL_B                   COL_C
---------- ----------------------- ---------
         1 whatever                13-JUN-10
         1                         12-JUN-10

SQL> var rc refcursor
SQL> exec :rc := get_table_a(1)

PL/SQL procedure successfully completed.

SQL> print rc

     COL_A COL_B                   COL_C
---------- ----------------------- ---------
         1 whatever                13-JUN-10
         1 something               12-JUN-10

SQL>

Dalam fungsi itu perlu untuk membuat instance tipe dengan kolom, untuk menghindari pengecualian ORA-00947. Ini tidak diperlukan saat mengisi jenis tabel PL/SQL:

SQL> create or replace procedure pop_table_a
  2        (p_arg in number)
  3  is
  4      type table_a_nt is table of table_a%rowtype;
  5      tab_a_recs table_a_nt;
  6  begin
  7      select *
  8      bulk collect into tab_a_recs
  9      from table_a
 10      where col_a = p_arg;
 11  end;
 12  /

Procedure created.

SQL> 

Terakhir, pedoman

"Apa yang harus menjadi pedoman Kapan menggunakan dan Kapan harus menghindari GTT"

Tabel temp global sangat baik ketika kita perlu berbagi data cache antara unit program yang berbeda dalam sesi yang sama. Misalnya jika kita memiliki struktur laporan umum yang dihasilkan oleh satu fungsi yang memberi makan GTT yang diisi oleh salah satu dari beberapa prosedur. (Meskipun itu juga dapat diimplementasikan dengan kursor ref dinamis ...)

Tabel sementara global juga bagus jika kita memiliki banyak pemrosesan menengah yang terlalu rumit untuk diselesaikan dengan satu kueri SQL. Terutama jika pemrosesan itu harus diterapkan ke subset dari baris yang diambil.

Namun secara umum anggapan seharusnya bahwa kita tidak perlu menggunakan tabel sementara. Jadi

  1. Lakukan dalam SQL kecuali jika terlalu sulit dalam hal ini ...
  2. ... Lakukan dalam variabel PL/SQL (biasanya koleksi) kecuali jika terlalu banyak memori yang diperlukan ...
  3. ... Lakukan dengan Tabel Sementara Global


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Haruskah saya menghapus atau menonaktifkan baris dalam database relasional?

  2. EM 12c Menyesuaikan Nilai Ambang Batas

  3. Statistik Tabel GTT dan SYS.WRI$_OPTSTAT_TAB_HISTORY

  4. ORA-08177:tidak dapat membuat serial akses untuk transaksi ini

  5. Setara dengan tabel eksternal Oracle di SQL Server