2016-10-07 24 views
5

niestety jedną kolumnę z ogromnym stole ma zerowy połowy danych, więc gdy kwerendaOracle zmiany indeksu, aby umożliwić indeks wartości null

select count(*) from huge_table where half_null_col is null; 

będzie katastrofa wydajność nawet jeśli jest już indeksowane:

create index half_null_col_idx on huge_table(half_null_col asc); 

Istnieją dwa pytania:

  1. Oracle 11g powinien support a constant expression to index on null values, ale Przepraszam, że przeszedłem przez docenta, ale nie mogłem znaleźć wyraźnego oficjalnego dokumentu na ten temat. Udostępnij referencję, jeśli ktokolwiek wie,

  2. jak zmienić indeks zamiast drop i create ponownie, aby uniknąć problemów z wydajnością.

+0

Jakie odniesienie jest potrzebne w "wyrażeniu stałym do indeksowania wartości zerowych"? Po prostu użyj go i zadziała. – nop77svk

Odpowiedz

6

mieć co najmniej cztery opcje, które przychodzą mi do głowy w tej chwili:

  1. utworzyć "stała wyrażenie" indeks ...

    create index half_null_col_idx 
    on huge_table (half_null_col, 1); 
    
  2. stworzyć bitmapę indeks na stole. indeksy bitmapowe pozwolić na wartości null indeksowania oraz ...

    create bitmap index half_null_col_idx 
    on huge_table (half_null_col); 
    
  3. Tworzenie indeksu na funkcji opartych NULL-odwzorować-to-coś wartości i wykorzystanie odwzorować NULL w zapytaniach zamiast wysyłania zapytań o wartości null .. .

    create index half_null_col_idx 
    on huge_table (nvl(half_null_col, '<a value that does not appear in the values of the column>')); 
    
    select * 
    from huge_table 
    where nvl(half_null_col, '<a value that does not appear in the values of the column>') 
        = '<a value that does not appear in the values of the column>' 
    ; 
    
  4. Repartition tabeli, tak aby wartości NULL pójść na całość w jednej partycji, a reszta wartości do różnych partycji/partycjach ...

    create table huge_table_2 
    partition by list (half_null_col) 
    (
        partition pt_nulls values (null), 
        partition pt_others values (default) 
    ) 
    as 
    select * 
    from huge_table; 
    

Jeśli wybierzesz tylko count(*) od stołu to indeks bitmap może być najlepszym rozwiązaniem.

Jeśli chcesz użyć pełnych rzędów danych z tabeli w innym miejscu (w połączeniu z inną tabelą lub wyeksportować je do pliku CSV lub cokolwiek innego), najlepszym rozwiązaniem może być ponowne utworzenie partycji.

Jeśli nie możesz/nie chcesz podzielić tabelki na partycje i nie możesz utworzyć indeksu bitmapy (np. Z powodu dużej współbieżnej aktywności DML w tabeli), wówczas indeks "stałego wyrażenia" lub Indeks "NULL-remapped-to-something" może być najlepszą opcją.


Aby odpowiedzieć oryginalne pytania:

  1. Oracle wewnętrznie zbliża się je jako "indeksów funkcyjnych na bazie". Być może szukaj tego terminu.
  2. Nie możesz. Nie ma jednak istotnego narzutu na wydajność w przypadku spadku indeksu online + tworzenie afaik.Oracle DB jest wystarczająco dobry, aby zadbać o "wielozadaniowość" - tworzenie indeksu razem z aplikacją działającą tak szybko, jak wcześniej. Jeśli chcesz odtworzyć indeks, po prostu to zrób. A jeśli wybierzesz opcję "stałego wyrażenia", możesz najpierw utworzyć nowy indeks, a następnie upuścić stary.
+0

kciuki za wspaniałą odpowiedź :) – Dreamer