2010-07-21 32 views
11

Używamy indeksu Oracle Text CTXSYS.CONTEXT do indeksowania około pół miliona wierszy zawierających metainformację. Informacje są rozłożone na dwie tabele, które są połączone przez procedurę, którą wywoływacz wywołuje w czasie wykonywania (indeks funkcjonalny).Przyspiesz indeksowanie Oracle Text lub pozwól indeksatorowi pracować tylko przy niskich czasach ładowania

Po uruchomieniu CREATE INDEX na moim komputerze lokalnym (zwykły notebook dualcore) indeks jest budowany w ciągu około 3 minut. Na naszym serwerze DB, który działa na systemie Solaris z 8 rdzeniami i 16 GB pamięci RAM, utworzenie całego indeksu dla tych samych (dokładnie takich samych) danych zajmuje około 24 godzin. Kod

Próbka: To jest nasz podajnik indeks dla dwóch tabel i 3 kolumny:

create or replace procedure docmeta_revisions_text_feeder 
    (p_rowid in rowid , p_clob in out nocopy clob) as v_clob CLOB begin 
    FOR c1 IN (select DM.DID, DM.XDESCRIB || ' ' || DM.XAUTHOR AS data 
     from DOCMETA DM 
     WHERE ROWID = p_rowid) 
    LOOP 
     v_clob := v_clob || c1.data; 
     FOR c2 IN (
      SELECT ' ' || RV.DDOCTITLE AS data 
      FROM REVISIONS RV 
      WHERE RV.DID = c1.DID) 
     LOOP 
      v_clob := v_clob || c2.data; 
     END LOOP; 
    END LOOP; 
    p_clob := v_clob;  
    end docmeta_revisions_text_feeder 

Są preferencje

BEGIN 
CTX_DDL.CREATE_PREFERENCE ('concat_DM_RV_DS', 'USER_DATASTORE'); 
CTX_DDL.SET_ATTRIBUTE ('concat_DM_RV_DS', 'PROCEDURE', 
'docmeta_revisions_text_feeder'); 
END; 

Teraz możemy utworzyć indeks

CREATE INDEX concat_DM_RV_idx ON DOCMETA (FULLTEXTIDX_DUMMY) 
INDEXTYPE IS CTXSYS.CONTEXT 
PARAMETERS ('datastore concat_DM_RV_DS 
section group CTXSYS.AUTO_SECTION_GROUP 
') PARALLEL 4; 

Dane składają się głównie z prostego tytułu lub nazwiska autora + krótki opis z tekstem < 1k.

Próbowałem trochę zagrać z włączonymi ustawieniami pamięci i parametrem PARALLEL, ale nie odniosłem żadnego sukcesu. Oto moje pytania:

  • Czy istnieje sposób na wstrzymanie i wznowienie procesu indeksowania (mam do dyspozycji rolę CTX_SYS)?
  • ma ktoś podpowiedź, który parametr można poprawić (szczególnie rozmiar pamięci)?
  • Czy można eksportować i importować indeks tekstowy? -> wtedy mógłbym przeprowadzić indeksowanie na mojej lokalnej maszynie i po prostu skopiować go na nasz serwer
  • czy indeksator może działać z "niższym priorytetem"?
  • Możliwe jest, że indeksowanie zostało zakłócone przez operacje blokowania (jest to maszyna pośrednicząca, do której inni mają dostęp równolegle). Czy istnieje sposób na zablokowanie zaangażowanych tabel, utworzenie indeksu i odblokowanie ich później?

Odpowiedz

9

W końcu zorientowaliśmy się, jak wykonać podzieloną synchronizację indeksu. Oto kilka podstawowych kroków, które pokazują, co zrobiliśmy:

CREATE INDEX concat_DM_RV_idx ON DOCMETA (FULLTEXTIDX_DUMMY) 
INDEXTYPE IS CTXSYS.CONTEXT 
PARAMETERS ('datastore concat_DM_RV_DS section group CTXSYS.AUTO_SECTION_GROUP 
NOPOPULATE 
'); 

patrz parametr NOPOPULATE? to znaczy, że indeksator nie powinien rozpoczynać procesu zapełniania/indeksowania. Jeśli masz 11 g, masz teraz bardzo dobrą funkcję CTX_DDL, która zapełnia indeks według woli, a mianowicie procedurę "POPULATE_PENDING". Wywołanie go na nazwie indeksu spowoduje wypełnienie tabeli CTXSYS zawierającej wiersze, które zostały zmodyfikowane, a zatem nie są zsynchronizowane. Zwróć uwagę, że po wywołaniu tej metody indeksator wciąż nic nie zaczął. Od 10 g (?) Procedura według CTX_DDL.SYNC_INDEX ma kilka dodatkowych parametrów, np. parametr "maxtime". Podaj go, powiedzmy, 4H, a indeksator rozpocznie synchronizację oczekujących wierszy przez około 4 godziny. Powtarzasz tę procedurę według harmonogramu i są gotowe.

To niestety nie działa w 9i. Próbowaliśmy więc "zasymulować" proces Oracle POPULATE_PENDING. Jedynym ograniczeniem dla tej metody jest: potrzebujesz jakiegoś unikalnego identyfikatora wiersza, aby móc odpytywać fragmenty tej samej treści ze swojej tabeli.Oto co zrobiliśmy:

1.) Utwórz indeks za pomocą NOPOPULATE (patrz wyżej) 2.) Zostań SYS/DBA/CTXSYS (tak, możesz do tego wezwać swojego administratora). Dowiedzieć się, że identyfikator świeżo utworzony indeks przez odpytywanie tabeli indeksu meta:

SELECT IDX_ID FROM CTXSYS.CTX_INDEXES WHERE IDX_NAME ='concat_DM_RV_idx'; 

3.) Zauważ, identyfikator indeksu to przynosi na żółtym fragmencie papieru i wykonanie tego komunikatu reklamowego CTXSYS roli i zastąpić <> z twoim indeksem id i <> z nazwą tabeli, na której zbudowany jest indeks. Unikalna rząd identifer może być jakiś ID dokumentu lub jakakolwiek policzalnych stwierdzeniem, że tworzy unikalny fragment danych z tabeli:

INSERT INTO CTXSYS.DR$PENDING (PND_CID,PND_PID,PND_ROWID,PND_TIMESTAMP) 
SELECT <<your index id>>, 0, <<basetable name>>.ROWID, CURRENT_DATE 
FROM gsms.DOCMETA 
WHERE <<basetable unique row identifier>> < 50000; 
COMMIT; -- Dont forget the COMMIT! DONT FORGET IT!!! WE MEAN IT! 

z „50,000” oznaczającą liczbę wierszy w zależności od rzadkość twojego basetabel, która zostanie wstawiona do oczekującej tabeli wierszy jako ładunek indeksu. Dostosuj go do własnych potrzeb.

4.) Teraz ustawiliśmy, aby zwolnić wskaźnik.

CALL CTX_DDL.SYNC_INDEX(
    'CONCAT_DM_RV_IDX', -- your index name here 
    '100M', -- memory count 
    NULL, -- param for partitioned idxes 
    2 -- parallel count 
); 

rozpocznie proces indeksowania na co liczyć wierszy umieściłeś w punkcie 3.), aby uruchomić następny kawałek powtórz krok 3.) z następnych 50.000 lub tak wierszy ("gdzie id pomiędzy 50.000 a 100.000 ")

Jeśli przypadkowo uruchomisz indeksowanie w tym samym zestawie wierszy, indeks mocno się rozpadnie. Jedynym sposobem na jego wyczyszczenie jest zoptymalizowanie indeksu za pomocą parametru REBUILD. Na naszym lokalnym komputerze, który był bardzo szybki, ponieważ podziałowe nie musi uciekać, ale tylko przestawia zawartość tabel indeksu:

CALL CTX_DDL.OPTIMIZE_INDEX('CONCAT_DM_RV_IDX', 'REBUILD'); 

Jeśli potrzebujesz jakiś meta informacje o statusie indeksowania i wielkości można poprosić CTX_REPORT pakiet:

SELECT CTX_REPORT.INDEX_SIZE('CONCAT_DM_RV_IDX') FROM DUAL; 

A jeśli zapomniałeś, które parametry wybrał na czas indeksowania:

SELECT * FROM CTXSYS.CTX_PARAMETERS; 

Szczęśliwa indeksowanie!

+0

Dziękuję za twoje badania. – egor7

+0

Świetne napisy, zajęło mi tygodnie, aby dowiedzieć się tyle. Jednak populate_pending POPULUJE listę aktualizacji indeksu PENDING z wszystkimi wierszami/dokumentami w tabeli źródłowej. Oracle nie ma pojęcia, co mogło się zmienić, w końcu śledzenie tego, co się zmieniło, jest dokładnie tym, za co odpowiada CTXSYS.DR $ PENDING. Użyj tego tylko podczas tworzenia indeksu lub jeśli chcesz ponownie zindeksować wszystko. – Roy