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

Masalah dengan variabel pengikat Oracle tidak menggunakan indeks dengan benar

Ini adalah topik yang lebih besar, tetapi ini adalah pendekatan yang menurut saya paling mudah untuk diterapkan dan berfungsi dengan baik. Triknya adalah dengan menggunakan SQL dinamis, tetapi menerapkannya sehingga Anda selalu melewati jumlah parameter yang sama (diperlukan), DAN Anda mengizinkan Oracle untuk melakukan hubungan pendek ketika Anda tidak memiliki nilai untuk parameter (apa yang Anda kurang dalam pendekatan Anda saat ini). Misalnya:

set serveroutput on
create or replace procedure test_param(p1 in number default null, p2 in varchar2 default null) as
  l_sql varchar2(4000);
  l_cur sys_refcursor;
  l_rec my_table%rowtype;
  l_ctr number := 0;
begin

  l_sql := 'select * from my_table where 1=1';
  if (p1 is not null) then
    l_sql := l_sql || ' and my_num_col = :p1';
  else
    -- short circuit for optimizer (1=1)
    l_sql := l_sql || ' and (1=1 or :p1 is null)';
  end if;

  if (p2 is not null) then
    l_sql := l_sql || ' and name like :p2';
  else
    -- short circuit for optimizer (1=1)
    l_sql := l_sql || ' and (1=1 or :p2 is null)';
  end if;

  -- show what the SQL query will be
  dbms_output.put_line(l_sql);

  -- note always have same param list (using)
  open l_cur for l_sql using p1,p2;

  -- could return this cursor (function), or simply print out first 10 rows here for testing
  loop
    l_ctr := l_ctr + 1;
    fetch l_cur
    into l_rec;
    exit when l_cur%notfound OR l_ctr > 10;

    dbms_output.put_line('Name is: ' || l_rec.name || ', Address is: ' || l_rec.address1);
  end loop;
  close l_cur;
end;

Untuk menguji, cukup jalankan. Misalnya:

set serveroutput on
-- using 0 param
exec test_param();
-- using 1 param
exec test_param(123456789);
-- using 2 params
exec test_param(123456789, 'ABC%');

Di sistem saya, tabel yang digunakan lebih dari 100mm baris dengan indeks pada bidang angka dan bidang nama. Kembali hampir seketika. Perhatikan juga bahwa Anda mungkin tidak ingin melakukan pemilihan * jika Anda tidak membutuhkan semua kolom, tetapi saya agak malas dan menggunakan %rowtype untuk contoh ini.

Semoga membantu



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Abaikan parameter rentang tanggal di klausa where saat parameter tidak dimasukkan

  2. Oracle Unicode Spooling

  3. Ketergantungan Oracle.DataAccess.Client

  4. Pilih nilai elemen xml di Oracle

  5. Mekanisme yang Diikuti oleh Oracle saat kami mengambil cadangan panas