2010-07-21 10 views
11

Stiamo utilizzando un indice CTXSYS.CONTEXT di Oracle Text per indicizzare circa mezzo milione di righe contenenti metainformazioni. Le informazioni sono distribuite su due tabelle combinate da una procedura che l'indicizzatore chiama in fase di runtime (indice funzionale).Accelerare l'indicizzazione di Oracle Text o lasciare che l'indicizzatore funzioni solo su tempi di caricamento bassi

Quando eseguo CREATE INDEX sulla mia macchina locale (notebook dualcore semplice) l'indice è costruito in circa 3 minuti. Sul nostro server DB che gira su Solaris con 8 core e 16G di RAM ci vogliono circa 24 ore per creare un indice per gli stessi (esattamente identici) dati. Codice

Esempio: Questo è il nostro alimentatore indice per due tavoli e 3 colonne:

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 

Queste sono le preferenze

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; 

Ora creiamo l'indice

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; 

I dati consistono principalmente in un semplice titolo o nome dell'autore + una breve descrizione con < 1k testo.

Ho provato a giocare un po 'con le impostazioni di memoria coinvolte e il parametro PARALLEL ma non ho avuto successo. Quindi, ecco che arrivano le mie domande:

  • c'è un modo per mettere in pausa e riprendere un processo di indicizzazione (ho il ruolo CTX_SYS a portata di mano)?
  • Qualcuno ha un suggerimento su quale parametro potrebbe essere modificato (in particolare la dimensione della memoria)?
  • è possibile esportare e importare un indice di testo? -> allora potrei eseguire l'indicizzazione sul mio computer locale e semplicemente copiarlo sul nostro server
  • un indicizzatore può essere eseguito con "priorità inferiore"?
  • è possibile che l'indicizzatore sia stato disturbato dalle operazioni di blocco (è una macchina di staging che l'altro accede in parallelo). C'è un modo per bloccare le tabelle coinvolte, creare l'indice e sbloccarle in seguito?

risposta

9

Abbiamo finalmente capito come eseguire una sincronizzazione suddivisa dell'indice. Ecco alcuni passaggi fondamentali che mostrano quello che abbiamo fatto:

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 
'); 

vedere il parametro NOPOPULATE? che dice l'indicizzatore che non dovrebbe avviare il processo di popolamento/indicizzazione. Se sei su 11g ora hai a portata di mano una funzionalità CTX_DDL molto bella che popola l'indice a piacimento, ovvero la procedura "POPULATE_PENDING". Chiamandolo sul nome dell'indice verrà compilata la tabella CTXSYS che contiene le righe che sono state modificate e pertanto non sincronizzate. Si noti che dopo aver chiamato questo metodo, l'indicizzatore non ha ancora avviato nulla. Poiché 10g (?) La procedura CTX_DDL.SYNC_INDEX secondo ha molti parametri aggiuntivi, ad es. il parametro "maxtime". Forniscilo con, diciamo, 4H e il tuo indicizzatore inizierà a sincronizzare le righe in sospeso per circa 4 ore. Ripeti quella procedura secondo programma e hai finito.

Che purtroppo non funziona in 9i. Così abbiamo provato a "simulare" il processo Oracle POPULATE_PENDING con successo. L'unica restrizione su questo metodo è la seguente: è necessario un qualche tipo di identificatore di riga univoco per poter interrogare pezzi dello stesso contenuto dalla tabella.Ecco cosa abbiamo fatto:

1.) Creare l'indice con NOPOPULATE (vedere sopra) 2.) Diventa SYS/DBA/CTXSYS (sì, potresti chiamare l'amministratore per quello). Scopri l'ID che l'indice appena creato ha interrogando l'indice meta tavolo:

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

3.) notare l'ID indice di questo sta dando su un frammento di carta gialla e eseguire questa istruzione di inserimento come ruolo CTXSYS e sostituire lo <> con l'ID dell'indice e lo <> con il nome della tabella su cui è stato creato l'indice. L'identificatore riga univoco può essere una sorta di ID documento o qualsiasi tipo di dichiarazione numerabile che crea un pezzo unico di dati della tabella:

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! 

Il "50.000" segna il numero di righe in base alla scarsità del vostro basetabel che verrà inserito nella tabella delle righe in sospeso come payload per l'indicizzatore. Regola per le tue esigenze.

4.) Ora siamo impostati per liberare l'indicizzatore.

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

inizierà il processo di indicizzazione su qualunque numero di righe che avete inserito al punto 3.) Per eseguire il ripetere il passo successivo pezzo 3.), con i prossimi 50.000 o giù di file ("dove id tra 50.000 e 100.000 ")

Se si esegue accidentalmente l'indicizzatore sullo stesso set di righe, l'indice sarà fortemente frammentato. L'unico modo per ripulirlo è ottimizzare l'indice con un parametro REBUILD. Sulla nostra macchina locale che era estremamente veloce in quanto l'indicizzatore non ha bisogno di correre, ma riordina solo il contenuto delle tabelle di indice:

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

Se avete bisogno di un po 'di meta-informazioni sullo stato di indicizzazione e le dimensioni si può chiedere al CTX_REPORT pacchetto:

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

E se ti sei dimenticato quali parametri si è scelto il tempo di indicizzazione:

SELECT * FROM CTXSYS.CTX_PARAMETERS; 

indicizzazione felice!

+0

Grazie per la tua ricerca. – egor7

+0

Un bel riassunto, mi ci sono voluti settimane per capirlo. Tuttavia, popola_pending POPOLA l'elenco degli aggiornamenti dell'indice PENDING con TUTTE le righe/i documenti nella tabella di origine. Oracle non ha idea di cosa potrebbe essere cambiato, dopo tutto, tenere traccia di ciò che è cambiato è esattamente ciò che CTXSYS.DR $ PENDING è per. Usalo solo quando crei l'indice o se vuoi reindicizzare tutto. – Roy

Problemi correlati