加速Oracle Text索引或让索引器仅在低负载时间工作

Ste*_*fan 12 oracle full-text-indexing database-tuning

我们使用Oracle Text CTXSYS.CONTEXT索引来索引包含元信息的大约50万行.信息分布在两个表中,这两个表由索引器在运行时调用的过程(功能索引)组合在一起.

当我在本地机器(简单的双核笔记本)上运行CREATE INDEX时,索引在大约3分钟内构建.在我们的数据库服务器上运行在具有8个内核和16G内存的Solaris上,需要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
Run Code Online (Sandbox Code Playgroud)

这些是偏好

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;
Run Code Online (Sandbox Code Playgroud)

现在我们创建索引

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;
Run Code Online (Sandbox Code Playgroud)

数据主要包括一个简单的标题或作者姓名+一个<1k文本的简短描述.

我尝试使用所涉及的内存设置和PARALLEL参数稍微玩一下,但没有任何成功.所以这里有我的问题:

  • 有没有办法暂停和恢复索引过程(我手头有CTX_SYS)?
  • 有人提示哪个参数可以调整(特别是内存大小)?
  • 是否可以导出和导入文本索引? - >然后我可以在我的本地机器上执行索引,只需将其复制到我们的服务器
  • 索引器能以"较低优先级"运行吗?
  • 索引器可能受到锁定操作的干扰(它是其他并行访问的暂存机器).有没有办法锁定所涉及的表,创建索引并在之后解锁它们?

Ste*_*fan 10

我们终于想出了如何对索引进行拆分同步.以下是一些显示我们所做工作的基本步骤:

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
');
Run Code Online (Sandbox Code Playgroud)

看到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(是的,你可能会打电话给你对于管理员).通过查询索引元表找出新创建的索引所具有的ID:

SELECT IDX_ID FROM CTXSYS.CTX_INDEXES WHERE IDX_NAME ='concat_DM_RV_idx';
Run Code Online (Sandbox Code Playgroud)

3)注意这是在一张黄色片段产生索引ID并执行此插入语句作为CTXSYS作用,并用食指ID和<>与该指数是建立在表的名称替换<>.唯一行标识符可以是某种文档ID或任何类型的可计数语句,用于创建表的唯一数据块:

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!
Run Code Online (Sandbox Code Playgroud)

该"50.000",标志着这取决于你basetabel的珍异那将在未决行表中插入有效载荷为索引的行数.根据自己的需要调整它.

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
);
Run Code Online (Sandbox Code Playgroud)

即将于任何的行数,您已插入在步骤3索引过程)要运行一个块重复步骤3)与下一50.000左右行("里50.000和100.000之间的ID")

如果您不小心在同一组行上运行索引器,索引将强烈碎片化.清理它的唯一方法是使用REBUILD参数优化索引.在我们的本地机器上,由于索引器不必运行但只重新排列索引表的内容,因此速度非常快:

CALL CTX_DDL.OPTIMIZE_INDEX('CONCAT_DM_RV_IDX', 'REBUILD');
Run Code Online (Sandbox Code Playgroud)

如果您需要有关索引状态和大小的元信息,可以询问CTX_REPORT包:

SELECT CTX_REPORT.INDEX_SIZE('CONCAT_DM_RV_IDX') FROM DUAL;
Run Code Online (Sandbox Code Playgroud)

如果您忘记了在索引时选择了哪些参数:

SELECT * FROM CTXSYS.CTX_PARAMETERS;
Run Code Online (Sandbox Code Playgroud)

快乐索引!