Ускорьте индексацию Oracle Text или дайте индексатору работать только при низкой загрузке - PullRequest
12 голосов
/ 21 июля 2010

Мы используем индекс Oracle Text CTXSYS.CONTEXT, чтобы индексировать около полумиллиона строк, содержащих метаинформацию.Информация распространяется по двум таблицам, которые объединяются процедурой, которую индексатор вызывает во время выполнения (функциональный индекс).

Когда я запускаю CREATE INDEX на моей локальной машине (простой двухъядерный ноутбук), индекс создаетсяоколо 3 минут.На нашем сервере БД, который работает на Solaris с 8 ядрами и 16 ГБ ОЗУ, для создания индекса для тех же (точно таких же) данных требуется около 24 часов.

Пример кода: Этонаш фидер индекса для двух таблиц и 3 столбцов:

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

Это настройки

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;

Теперь мы создаем индекс

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;

Данные в основном состоят из простого названия или имени автора + краткое описание с текстом <1k. </p>

Я попытался немного поиграть с настройками памяти и PARALLEL.параметр, но не имеют успеха.Итак, вот мои вопросы:

  • Есть ли способ приостановить и возобновить процесс индексации (у меня есть роль CTX_SYS)?
  • есть кто-нибудь подсказка, какой параметр может бытьнастроено (особенно объем памяти)?
  • можно ли экспортировать и импортировать текстовый индекс?-> тогда я мог бы выполнить индексацию на моем локальном компьютере и просто скопировать ее на наш сервер
  • , может ли индексатор работать с «более низким приоритетом»?
  • возможно, что индексатор былнарушается операциями блокировки (это инсценировка машины, доступ к которой параллельно у других).Есть ли способ заблокировать соответствующие таблицы, создать индекс и впоследствии разблокировать их?

1 Ответ

10 голосов
/ 28 июля 2010

Наконец-то мы выяснили, как выполнить разделенную синхронизацию индекса.Вот несколько основных шагов, которые показывают, что мы сделали:

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

см. Параметр NOPOPULATE?это говорит индексатору, что он не должен запускать процесс заполнения / индексации.Если вы на 11g, у вас есть очень хорошая функция CTX_DDL, которая заполняет индекс по желанию, а именно процедура «POPULATE_PENDING».Вызов его по имени индекса заполняет таблицу CTXSYS, в которой хранятся строки, которые были изменены и, следовательно, не синхронизированы.Обратите внимание, что после вызова этого метода индексатор все еще ничего не запускает.Начиная с 10g (?) Соответствующая процедура CTX_DDL.SYNC_INDEX имеет несколько дополнительных параметров, например, параметр «maxtime».Предоставьте ему, скажем, 4H, и ваш индексатор начнет синхронизировать ожидающие строки в течение примерно 4 часов.Вы повторяете эту процедуру по расписанию, и все готово.

К сожалению, это не работает в 9i.Поэтому мы попытались «смоделировать» процесс Oracle POPULATE_PENDING.Единственное ограничение для этого метода: вам нужен какой-то уникальный идентификатор строки, чтобы иметь возможность запрашивать куски того же контента из вашей таблицы.Вот что мы сделали:

1.) Создайте индекс с помощью NOPOPULATE (см. Выше) 2.) Станьте SYS / DBA / CTXSYS (да, вы можете позвонить своему администратору для этого).Найдите идентификатор, который имеет только что созданный вами индекс, с помощью запроса к таблице метаданных индекса:

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

3.) Запишите идентификатор индекса, который это дает на желтом фрагменте бумаги, и выполните этот оператор вставки как роль CTXSYS.и замените <> вашим идентификатором индекса, а <> именем таблицы, на которой построен индекс.Уникальный идентификатор строки может быть идентификатором документа или счетным оператором любого типа, который создает уникальный фрагмент данных вашей таблицы:

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!

«50.000» обозначает количество строк в зависимости от дефицитавашей базовой таблицы, которая будет вставлена ​​в таблицу ожидающих строк в качестве полезной нагрузки для индексатора.Отрегулируйте его под свои нужды.

4.) Теперь мы настроены на освобождение индексатора.

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

запустит процесс индексации для любого количества строк, вставленных на шаге 3.) Для запуска следующегоповторить шаг 3.) со следующими примерно 50 000 строк («где id между 50 000 и 100 000»)

Если вы случайно запустите индексатор для того же набора строк, индекс будет сильно фрагментирован.Единственный способ очистить его - оптимизировать индекс с помощью параметра REBUILD.На нашей локальной машине это было очень быстро, так как индексатор не должен работать, а только переупорядочивает содержимое таблиц индекса:

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

Если вам нужна мета-информация о состоянии и размере индексации, вы можете спроситьпакет CTX_REPORT:

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

И если вы забыли, какие параметры вы выбрали во время индексации:

SELECT * FROM CTXSYS.CTX_PARAMETERS;

Удачной индексации!

...