13

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

当我在本地机器(简单的双核笔记本)上运行 CREATE INDEX 时,索引会在大约 3 分钟内建立。在我们的数据库服务器上,它在 Solaris 上运行,具有 8 个内核和 16G 的 RAM,它需要大约 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 文本的简短描述组成。

我尝试对涉及的内存设置和 PARALLEL 参数进行一些尝试,但没有任何成功。所以我的问题来了:

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

1 回答 1

12

我们终于弄清楚了如何对索引进行拆分同步。以下是展示我们所做工作的一些基本步骤:

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(是的,您可以为此致电您的管理员)。通过查询索引元表找出新创建的索引的 ID:

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

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!

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

将在您在步骤 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;

快乐索引!

于 2010-07-28T07:51:54.117 回答