Mam tabelę, która ma aktywne nieaktywne wpisy, aktywna = 1 dla aktywnych i aktywna = 0 dla nieaktywnych.
Mam różne indeksy na tej tabeli, ale japotrzebne są tylko indeksy utrzymywane dla aktywnych wpisów, ponieważ aplikacja odpytuje tylko o aktywne dane. Nieaktywne dane muszą być przechowywane, ponieważ mogą ponownie stać się aktywne, ale zazwyczaj odbywa się to tylko przy zbiorczych aktualizacjach, które i tak nie używają indeksu.
Zauważam, że indeksowanie nieaktywnych wpisów (jest ich więcej niż aktywnych) zajmuje sporo miejsca.
Czy w Oracle (10g) jest sposób na zrobienie czegoś takiego:
create index an_idx on tab (active, col1, col2, ... , coln) where active = 1
?
Poprzednia próba:
Próbowałem użyć indeksu opartego na funkcji, aby ustawić pierwszą kolumnę na null, gdy active = 0
jak na przykład:
create index an_idx on tab (decode(active, 1, 1, null), col1, col2, ... , coln)
Jednak Oracle nadal wydaje się indeksować nieaktywne kolumny w tym przypadku.
Odpowiedzi:
7 dla odpowiedzi № 1Podziel tabelę na ACTIVE, utwórz indeksy lokalne i uczyń indeksy nieaktywnych partycji NIEDOPUSZCZALNE. Pozwoli to wyeliminować czas poświęcony na indeksowanie nieaktywnych danych.
create table tab(active number, col1 number, col2 number, col3 number)
partition by list(active)
(partition tab_active values(1), partition tab_inactive values(0));
create index tab_index1 on tab(col1) local;
alter index tab_index1 modify partition tab_inactive unusable;
Istnieje jednak kilka potencjalnych wad tego podejścia:
- Nie wszystkie typy indeksów mogą być bezużyteczne.
- Nie jest normalne, że w bazie danych znajdują się obiekty, które nie nadają się do użytku. Ludzie prawdopodobnie narzekają na to lub zakładają, że jest to błąd i odbudowuje go.
- Niektóre operacje, takie jak obcinanie, automatycznie ponownie nadają indeksom użyteczność.
W Oracle 12c możesz tego dokonać indeksy częściowe:
create table tab(active number, col1 number, col2 number, col3 number)
partition by list(active)
(partition tab_active values(1) indexing on,
partition tab_inactive values(0) indexing off);
create index tab_index1 on tab(col1) local indexing partial;
11 dla odpowiedzi nr 2
Twoja podstawowa idea jest właściwa, ale musisz zastosować dekodowanie do wszystkich kolumn. Tylko wtedy, gdy wszystkie indeksowane wyrażenia są NULL
czy wiersz nie zostanie zindeksowany.
create index an_idx on tab (
decode(active, 1, col1, null),
...
decode(active, 1, coln, null)
)
Oczywiście, jeśli chcesz, aby zapytanie używało tego indeksu, musi użyć tych samych wyrażeń w klauzuli WHERE.
Uwaga: Myślę, że nie chcesz dołączać wyrażenia decode(active, 1, 1, null)
w indeksie, ponieważ byłby stały dla wszystkich indeksowanych wierszy.
1 dla odpowiedzi nr 3
Nie sądzę, żeby to było możliwe. Istnieje kilka opcji
- Utwórz indeks (aktywny, col1 ...), aby nie wpływać na czas zapytania tyle samo przez nieaktywne elementy
- Utwórz dwie tabele dla aktywnych / nieaktywnych elementów i zarządzaj aktywnym stanem, przenosząc rzeczy między dwiema tabelami
- Utwórz drugą tabelę ze wszystkimi danymi, które chcesz zindeksować, a także unikatowy identyfikator i dołącz do tabeli, aby uzyskać pozostałe dane.