Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Problem polegający na tym, że zmienne wiążące Oracle nie używają poprawnie indeksu

To jest naprawdę większy temat, ale jest to podejście, które moim zdaniem jest najłatwiejsze do wdrożenia i działa dobrze. Sztuczka polega na użyciu dynamicznego SQL, ale zaimplementuj go tak, aby zawsze przekazywać tę samą liczbę parametrów (potrzebnych) ORAZ pozwolić Oracle na zwarcie, gdy nie masz wartości parametru (czego brakuje Twoje obecne podejście). Na przykład:

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;

Aby przetestować, po prostu go uruchom. Na przykład:

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

W moim systemie używana tabela ma ponad 100 mm wierszy z indeksem w polu numeru i polu nazwy. Zwraca niemal natychmiast. Pamiętaj też, że możesz nie chcieć wybierać *, jeśli nie potrzebujesz wszystkich kolumn, ale jestem trochę leniwy i używam %rowtype w tym przykładzie.

Mam nadzieję, że to pomoże



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Funkcja JSON_VALUE() w Oracle

  2. Instalowanie 32-bitowego klienta Oracle na serwerze Windows, na którym już działa 64-bitowy serwer bazy danych Oracle

  3. Wprowadzenie do natywnego dynamicznego SQL w bazie danych Oracle

  4. Podziel ciąg według pozycji ogranicznika za pomocą Oracle SQL

  5. Jak uzyskać aktualny obiekt Connection w Spring JDBC?