ITPUB 电子杂志

 2003 年 4 月号 (总第四期)



       ITPUB――信息技术新动力!
ITPub 电子杂志(总第四期)                                                    第2页




                            本期内容导读


 本期焦点:Ora...
ITPub 电子杂志(总第四期)                                                                                                第3页



目录
...
ITPub 电子杂志(总第四期)                                                     第4页



本期焦点

                  Oracle9i 中全文检索的创建与使用

...
ITPub 电子杂志(总第四期)                                                          第5页


有很多时候 使用 instr 和 like 是很理想的, 特别是搜索仅跨越很小的表的...
ITPub 电子杂志(总第四期)                                                          第6页




         (c) Copyright 1998 Oracle Corpo...
ITPub 电子杂志(总第四期)                                                               第7页


                (quick_id, text)
    ...
ITPub 电子杂志(总第四期)                                                      第8页




2 建立索引

2.1 索引简介

利用 Oracle Text 对文档集合进行检索的时...
ITPub 电子杂志(总第四期)                                                            第9页


 索引类型      描述                           ...
ITPub 电子杂志(总第四期)                                                        第 10 页


2.2.1 CONTEXT 索引的结构

Oracle Text 索引将文本打碎分...
ITPub 电子杂志(总第四期)                                                    第 11 页




可以看到,该表中保存的其实就是 Oracle 分析你的文档后,生成的 token 记录...
ITPub 电子杂志(总第四期)                                                      第 12 页




   Default CONTEXT Index Example

建立索引时,系...
ITPub 电子杂志(总第四期)                                                               第 13 页


       1.   文本存储在数据库中。可以是 CLOB, BL...
ITPub 电子杂志(总第四期)                                                                    第 14 页


 Datastore Type              ...
ITPub 电子杂志(总第四期)                                                          第 15 页


CREATE INDEX mc_idx ON mc(NAME) INDEXTY...
ITPub 电子杂志(总第四期)                                                            第 16 页


     VALUES (1, 2, 'Some more Oracle ...
ITPub 电子杂志(总第四期)                                                             第 17 页




区分组(Section Groups)是与 interMedia 一...
ITPub 电子杂志(总第四期)                                                        第 18 页


/

/* 也可以检索到 区段界限内的文本。但由于 HTML 文件中的一些标记如<...
ITPub 电子杂志(总第四期)                                                               第 19 页


2) 插入一个简单的文档(the DTD is not requir...
ITPub 电子杂志(总第四期)                                                                    第 20 页




  SELECT   id
    FROM   em...
ITPub 电子杂志(总第四期)                                                               第 21 页


2.3.3 Storage 类

Storage(存储空间)组的类只...
ITPub 电子杂志(总第四期)                                                                第 22 页


属性             属性值

             ...
ITPub 电子杂志(总第四期)                                                        第 23 页




Oracle 实现全文检索,其机制其实很简单。即通过 Oracle 专利的词法...
ITPub 电子杂志(总第四期)                                                         第 24 页


这样建立的全文检索索引,就会使用 chinese_vgram_lexer 作为分...
ITPub 电子杂志(总第四期)                                                      第 25 页




SPL_OWNER SPL_NAME        SPL_COUNT      ...
ITPub 电子杂志(总第四期)                                                      第 26 页




这节讲一下当索引操作失败的时候所要进行的一些处理。

3.1 查看索引错误

有时...
ITPub 电子杂志(总第四期)                                                            第 27 页


BEGIN
   ctx_ddl.drop_preference ('my...
ITPub 电子杂志(总第四期)                                                      第 28 页


对于 CTXCAT 类型的索引来说, 当对基表进行 DML 操作的时候,Oracle ...
ITPub 电子杂志(总第四期)                                                          第 29 页


idx_name     索引名称
memory       指定同步索引需要...
ITPub 电子杂志(总第四期)                                                      第 30 页


当新的文档被包含到表的时候,索引被同步。如果新行 DOC7 也包括单词 DOG,将会形...
ITPub 电子杂志(总第四期)                                                          第 31 页


   ctx_ddl.optimize_index ('myidx', 'fa...
ITPub 电子杂志(总第四期)                                                                    第 32 页


 WHERE contains (text, 'Oracl...
ITPub 电子杂志(总第四期)                                                               第 33 页




返回了得分最高的前 10 条记录.



5.2 Logical...
ITPub 电子杂志(总第四期)                                                                      第 34 页


  操作符 符号             描述    ...
ITPub 电子杂志(总第四期)                                                          第 35 页


CONTEXT 索引支持在分区表山建立本地分区索引,但仍然有一些限制。如下:
...
ITPub 电子杂志(总第四期)                                                           第 36 页


6.2 并行的创建一个本地分区索引

可以并行的建立分区索引,加快建立索引速...
ITPub 电子杂志(总第四期)                                                           第 37 页




而且配合 Lexer 参数很好的支持了中文字符集的检索。

具体实现方法...
ITPub 电子杂志(总第四期)                                                       第 38 页




指定路径带来的相关问题:
如 CTX_DDL.SET_ATTRIBUTE( 'm...
ITPub 电子杂志(总第四期)                                                                   第 39 页


URL_DATASTORE 参数

URL_DATASTOR...
ITPub 电子杂志(总第四期)                                                        第 40 页


建立索引,索引 Html 文件可以使用 HTML_SECTION_GROUP:

...
ITPub 电子杂志(总第四期)                                                           第 41 页


ORA-06512: 在"CTXSYS.TEXTINDEXMETHODS",...
ITPub 电子杂志(总第四期)                                                                第 42 页




解决:这是 intermedia 的某个 object 没有正...
ITPub 电子杂志(总第四期)                                                                   第 43 页


As a benchmark, with an averag...
ITPub 电子杂志(总第四期)                                                                      第 44 页




         Oracle Text Refe...
ITPub 电子杂志(总第四期)                                                                        第 45 页


This will create the inde...
ITPub 电子杂志(总第四期)                                                                第 46 页


unusable;

exec dbms_pclxutil.bui...
ITPub 电子杂志(总第四期)                                                                    第 47 页


Answer: The best way is to ti...
ITPub 电子杂志(总第四期)                                                        第 48 页


 String connStr="jdbc:Oracle:thin:@localh...
ITPub 电子杂志(总第四期)                                                           第 49 页


        DriverManager.registerDriver(n...
ITPub 电子杂志(总第四期)                                                           第 50 页


               else
                 c...
ITPub 电子杂志(总第四期)                                                        第 51 页



                         9i 新特点:SPFILE 的...
ITPub 电子杂志(总第四期)                                                      第 52 页


*
ERROR 位于第 1 行:
ORA-32002: 无法创建已由例程使用的 SPF...
ITPub 电子杂志(总第四期)                                                      第 53 页



二. 使用 SPFILE


重新启动数据库,使用 startup 命令,Oralc...
ITPub 电子杂志(总第四期)                                                            第 54 页




三. 使用 pfile/spfile 启动数据库

如果你想使用 pf...
ITPub 电子杂志(总第四期)                                                       第 55 页


SQL>


我们修改 PFILE 文件内容如下:


#Pfile link to...
ITPub 电子杂志(总第四期)                                                  第 56 页


系统已更改。



所以你也可以通过如上方式在启动时修改初始化参数。比我们在本文最后介绍的导入...
ITPub 电子杂志(总第四期)                                                        第 57 页




四. 修改参数


    可以通过 ALTER SYSTEM 或者导入导出来...
ITPub 电子杂志(总第四期)                                                         第 58 页


SQL> show parameter timed_statistics

NA...
ITPub 电子杂志(总第四期)                                                        第 59 页


timed_statistics                        b...
ITPub 电子杂志(总第四期)                                                       第 60 页


SQL> SHOW parameter timed_statistics

NAME...
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
Upcoming SlideShare
Loading in …5
×

Itpub电子杂志第四期第二稿

6,483 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
6,483
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Itpub电子杂志第四期第二稿

  1. 1. ITPUB 电子杂志 2003 年 4 月号 (总第四期) ITPUB――信息技术新动力!
  2. 2. ITPub 电子杂志(总第四期) 第2页 本期内容导读 本期焦点:Oracle 9i Oracle9i 中全文检索的创建与使用 Oracle 从 7.3 开始支持全文检索,在 Oracle9i 中这一功能被称为称为 Oracle Text。在这篇 文章里,玉面飞龙对 9i 的全文检索进行了详细而深入的研究。 9i 新特点:SPFILE 的使用 在 Oracle 9i 以前,Oracle 使用 pfile 存储初始化参数设置。在 Oracle9i 中,一个新的文件被 引入-spfile。eygle 在这里对这个看似简单的话题进行了细致的研究。 Oracle9i RAC 概述方案 Oracle9i 的 RAC 不仅仅是 OPS 的升级产品,本文提供关于 Oracle9i Real Application Server 的产品说明,优点,成功案例等内容。 Oracle RAC FOR HP 安装报告 理论还要结合实践。这篇安装报告介绍了在 HP 平台上实现 RAC 的具体方法,很具有的参考 性。 实际应用 高级数据迁移 很多时侯要在异构数据库之间进行数据迁移或抽取。如果在 SQL 中提取 ORACLE 的数据, 可以通过 ODBC、OLEDB 等多种方式,要从 ORACLE 提取 SQL 中的数据呢?看看这篇文 章就能找到答案。 备份策略 本文为大家提供了一份详尽的备份策略,极具参考价值。 论坛精华 关于 SGA 设置的一点总结 Biti_rainy 的在论坛上的精华帖子。给出了关于 SGA 设置的一个指导性的建议。 Home: http://www.itpub.net Mail: epub@itpub.net
  3. 3. ITPub 电子杂志(总第四期) 第3页 目录 本期焦点 ORACLE9I 中全文检索的创建与使用 作者:玉面飞龙 .................................................. 4 9I 新特点:SPFILE 的使用 作者:盖国强 (ITPUB:EYGLE) ...........................................51 ORACLE9I RAC 概述方案 作者:谢伟(ORACLEXIE) ....................................................69 ORACLE RAC FOR HP 安装报告 作者:谢伟(ORACLEXIE)..............................................75 实际应用 高级数据迁移 作者:谢中辉 .......................................................................................81 备份策略 作者:WEBKING .......................................................................................87 论坛精华 关于 SGA 设置的一点总结 作者:BITI_RAINY............................................................93 TIPS 将 ORACLE 加为 SQL SERVER 的链接服务器 作者:谢中辉 .........................................96 DB ENGLISH 关系数据库之父:DR. EDGAR FRANK CODD ..............................................................97 LINKS 超链接 ....................................................................................................................99 Home: http://www.itpub.net Mail: epub@itpub.net
  4. 4. ITPub 电子杂志(总第四期) 第4页 本期焦点 Oracle9i 中全文检索的创建与使用 作者:玉面飞龙 1 前言 Oracle 从 7.3 开始支持全文检索,即用户可以使用 Oracle 服务器的上下文(ConText)选项 完成基于文本的查询。具体可以采用通配符查找、模糊匹配、相关分类、近似查找、条件加 权和词意扩充等方法。 Oracle8.0.x 中称为 ConText ; Oracle8i 中称为 interMedia Text ; 在 在 Oracle9i 中称为 Oracle Text。 本篇主要介绍 Oracle Text 的基本结构和简单应用。 Oracle Text 是 9i 标准版和企业版的一部分。Oracle9i 将全文检索功能做为内置功能提供给 用户,使得用户在创建数据库实例时自动安装全文检索。 Oracle Text 的应用领域有很多: 搜索文本 :需要快捷有效搜索文本数据的应用程序 管理多种文档:允许搜索各种混和文档格式的应用程序,包括 ord,excel,lotus 等 从多种数据源中检索文本:不仅来自 Oracle 数据库中的文本数据,而且可以来自 Internet 和文件系统的文本数据 搜索 XML 应用程序 1.1 搜索文本 不使用 Oracle text 功能,也有很多方法可以在 Oracle 数据库中搜索文本.可以使用标准的 INSTR 函数和 LIKE 操作符实现. SELECT * FROM mytext WHERE INSTR (thetext, 'Oracle') > 0; SELECT * FROM mytext WHERE thetext LIKE '%Oracle%'; Home: http://www.itpub.net Mail: epub@itpub.net
  5. 5. ITPub 电子杂志(总第四期) 第5页 有很多时候 使用 instr 和 like 是很理想的, 特别是搜索仅跨越很小的表的时候.然而通过这些 文本定位的方法将导致全表扫描,对资源来说消耗比较昂贵,而且实现的搜索功能也非常有 限. 利用 Oracle Text,你可以回答如“在存在单词‘Oracle’的行同时存在单词’Corporation’而且 两单词间距不超过 10 个单词的文本‘,’查询含有单词’Oracle’或者单词’ california’的文 本,并且将结果按准确度进行排序‘,’含有词根 train 的文本‘。以下的 sql 代码实现了 如上功能。我们且不管这些语法是如何使用的。 DROP INDEX index mytext_idx / CREATE INDEX mytext_idx ON mytext( thetext ) INDEXTYPE is CTXSYS.CONTEXT / SELECT id FROM mytext WHERE contains (thetext, 'near((Oracle,Corporation),10)') > 0 / SELECT score (1), id FROM mytext WHERE contains (thetext, 'Oracle or california', 1) > 0 ORDER BY score (1) DESC / SELECT id FROM mytext WHERE contains (thetext, '$train') > 0; 1.2 设置 首先检查数据库中是否有 CTXSYS 用户和 CTXAPP 脚色。如果没有这个用户和角色,意味 着你的数据库创建时未安装 intermedia 功能。你必须修改数据库以安装这项功能。 还可以检查服务器是否有对 PLSExtProc 服务的监听。 lsnrctl status should give status LSNRCTL for Solaris: Version 8.1.5.0.0 - Production on 31-MAR-99 18:57:49 Home: http://www.itpub.net Mail: epub@itpub.net
  6. 6. ITPub 电子杂志(总第四期) 第6页 (c) Copyright 1998 Oracle Corporation. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC0))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Solaris: Version 8.1.5.0.0 - Production Start Date 30-MAR-99 15:53:06 Uptime 1 days 3 hr. 4 min. 42 sec Trace Level off Security OFF SNMP OFF Listener Parameter File /private7/Oracle/Oracle_home/network/admin/listener.ora Listener Log File /private7/Oracle/Oracle_home/network/log/listener.log Services Summary... PLSExtProc has 1 service handler(s) oco815 has 3 service handler(s) The command completed successfully Oracle 是通过所谓的‘外部调用功能’(external procedure)来实现 intermedia 的。 B. Create a user/table/index/query thus: As SYS or SYSTEM: ---------------------------------------------------------- CREATE USER ctxtest IDENTIFIED BY ctxtest; GRANT CONNECT, RESOURCE, ctxapp TO ctxtest; ---------------------------------------------------------- Do any other grants, quotas, tablespace etc. for the new user. As CTXTEST: ---------------------------------------------------------- CREATE TABLE quick ( quick_id NUMBER PRIMARY KEY, text VARCHAR(80)); INSERT INTO quick (quick_id, text) VALUES (1, 'The cat sat on the mat'); INSERT INTO quick Home: http://www.itpub.net Mail: epub@itpub.net
  7. 7. ITPub 电子杂志(总第四期) 第7页 (quick_id, text) VALUES (2, 'The quick brown fox jumped over the lazy dog'); COMMIT ; CREATE INDEX quick_text ON quick ( text ) INDEXTYPE IS ctxsys.CONTEXT; ---------------------------------------------------------- 此时如果监听没有配置好创建索引将会失败。 CREATE INDEX quick_text ON quick ( text ); * ERROR at line 1: ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine ORA-20000: ConText error: DRG-50704: Net8 listener is not running or cannot start external procedures ORA-28575: unable to open RPC connection to external procedure agent ORA-06512: at "CTXSYS.DRUE", line 122 ORA-06512: at "CTXSYS.TEXTINDEXMETHODS", line 34 ORA-06512: at line 1 如果一切正常,你将得到: Index created. 现在尝试写一些查询: SQL> SELECT quick_id FROM quick WHERE contains (text, 'cat') > 0; QUICK_ID ---------- 1 SQL> SELECT quick_id FROM quick WHERE contains(text, 'fox') > 0; QUICK_ID ---------- 2 Home: http://www.itpub.net Mail: epub@itpub.net
  8. 8. ITPub 电子杂志(总第四期) 第8页 2 建立索引 2.1 索引简介 利用 Oracle Text 对文档集合进行检索的时候,你必须先在你的文本列上建立索引。索引将 文本打碎分成很多记号(token),这些记号通常是用空格分开的一个个单词。 Oracle Text 应用的实现实际上就是一个 数据装载—> 索引数据—>执行检索 的一个过程。 2.1.1 索引类型和限制 建立的 Oracle Text 索引被称为域索引(domain index),包括 4 种索引类型: CONTEXT CTXCAT CTXRULE CTXXPATH 依据你的应用程序和文本数据类型你可以任意选择一种。可以利用 Create Index 建立这 4 种索引。下面说一下这 4 种索引的使用环境。 索引类型 描述 查询操作符 CONTEXT 用于对含有大量连续文本数据进行检索。支持 word、html、 CONTAINS xml、text 等很多数据格式。支持中文字符集, 支持分区索引, 唯一支持并行创建索引(Parallel indexing)的索引类型。 对表进行 DML 操作后,并不会自动同步索引。需要手工同步 Home: http://www.itpub.net Mail: epub@itpub.net
  9. 9. ITPub 电子杂志(总第四期) 第9页 索引类型 描述 查询操作符 索引 CTXCAT 当使用混合查询语句的时候可以带来很好的效率。适合于查 CATSEARCH 询较小的具有一定结构的文本段。具有事务性,当更新主表 的时候自动同步索引。 The CTXCAT index does not support table and index partitioning, documents services (highlighting, markup, themes, and gists) or query services (explain, query feedback, and browse words.) CTXRULE Use to build a document classification application. You MATCHES create this index on a table of queries, where each query has a classification. Single documents (plain text, HTML, or XML) can be classified by using the MATCHES operator. CTXXPATH Create this index when you need to speed up ExistsNode() queries on an XMLType column. Can only create this index on XMLType column. 在以上 4 种索引中,最常用的就是 CONTEXT 索引,使用最通用的 CONTAINS 操作符进行 查询。本篇主要针对的就是 Oracle Text ConText 的介绍。 2.1.2 权限和临时表空间 权限 用户不需要具有 CTXAPP 脚色便可以建立 Oracle Text 索引。你只需要对某一文本列 有创建 B 树索引的权限。查询用户,索引用户,表拥有者可以是不同的用户。 临时表空间要求 建立 Oracle Text 索引需要消耗 CTXSYS 用户默认的临时表空间空间。如果空间不够 的话将导致 ORA-01652 错误。你可以扩展 CTXSYS 的临时表空间,而不是发出命 令的用户默认的临时表空间。 对于索引全英文的文本列来说,需要临时表空间大小通常是其文本数据量的 50%-200%不等。而对索引包含中文文本列来说需要的表空间会更多。 2.2 CONTEXT 索引 Home: http://www.itpub.net Mail: epub@itpub.net
  10. 10. ITPub 电子杂志(总第四期) 第 10 页 2.2.1 CONTEXT 索引的结构 Oracle Text 索引将文本打碎分成很多的记号(token).例如文本‘I Love www.itpub.net’ 将会被分成 I ,LOVE,WWW,ITPUB,NET 这样的记号(token)。 Oracle Text CONTEXT 索引是反向索引(inverted index)。每个记号 (token)都映射着 包含它自己的文本位置。在索引建立过程中,单词 Cat 会包括如下的条目入口: Cat row1,row2,row3 表示 Cat 在行 row1、row2、row3 都出现过,这样通过查找单词所对应的行的 rowid 就可以 迅速找到文本记录。 在索引建好后,我们可以在该用户下查到 Oracle 自动产生了以下几个表:(假设索引名为 myindex):DR$myindex$I、DR$myindex$K、DR$myindex$R、DR$myindex$N 其中以 I 表最重要,可以查询一下该表,看看有什么内容: SQL> CREATE TABLE mytext (text VARCHAR2(100)); SQL> INSERT INTO mytext VALUES ('I Love www.itpub.net'); SQL> COMMIT; SQL> CREATE INDEX mytext_idx ON mytext(text) INDEXTYPE IS ctxsys.CONTEXT; SQL> SELECT token_text, token_count FROM dr$mytext_idx$i; TOKEN_TEXT TOKEN_COUNT I 1 ITPUB 1 LOVE 1 NET 1 WWW 1 注意 TOKEN_TEXT 里面字符全部是大写的,默认情况下全文索引是不区分大小写的. SQL> DESC dr$mytext_idx$i; 名称 是否为空 类型 TOKEN_TEXT NOT NULL VARCHAR2(64) TOKEN_TYPE NOT NULL NUMBER(3) TOKEN_FIRST NOT NULL NUMBER(10) TOKEN_LAST NOT NULL NUMBER(10) TOKEN_COUNT NOT NULL NUMBER(10) TOKEN_INFO BLOB Home: http://www.itpub.net Mail: epub@itpub.net
  11. 11. ITPub 电子杂志(总第四期) 第 11 页 可以看到,该表中保存的其实就是 Oracle 分析你的文档后,生成的 token 记录在这里,包 括 token 出现的位置、次数、hash 值等。 2.2.2 建立索引 建立索引的语法如下。索引建立好后可以用 ConTains 进行查询。 CREATE INDEX [schema.]index on [schema.]table(column) INDEXTYPE IS ctxsys.context [ONLINE] LOCAL [(PARTITION [partition] [PARAMETERS('paramstring')] [, PARTITION [partition] [PARAMETERS('paramstring')]])] [PARAMETERS(paramstring)] [PARALLEL n] [UNUSABLE]; 数据库用创建和插入这些索引的方法叫做索引管道(index Pipeline)。根据不同的参数构 建索引,可以应用于很多实际环境。 类别 描述 Datastore 从哪里得到数据? Filter 将数据转换成文本 Lexer 正在索引什么语言? Wordlist 应该如何展开茎干和模糊查询 Storage 如何存储索引 Stop List 什么单词或者主题不被索引? Section Group 允许在区段内查询吗?如何定义文档区段。这把文档转换成普通文 本 这些参数在建立 CONTEXT 索引过程中将按下图顺序对索引进程起作用。在本篇中提供一些 简单 demo 会看到各个参数的作用。 Home: http://www.itpub.net Mail: epub@itpub.net
  12. 12. ITPub 电子杂志(总第四期) 第 12 页 Default CONTEXT Index Example 建立索引时,系统默认文档存储在数据库的文本列中。如果不显示的指定索引参数,系统会 自动探测文本语言,数据类型和文档格式。 CREATE INDEX myindex ON docs(text) INDEXTYPE IS CTXSYS.CONTEXT; 如上命令建立了一个默认参数的 CONTEXT 索引 myindex.系统默认: Home: http://www.itpub.net Mail: epub@itpub.net
  13. 13. ITPub 电子杂志(总第四期) 第 13 页 1. 文本存储在数据库中。可以是 CLOB, BLOB, BFILE, VARCHAR2, or CHAR 类型 的文本数据。 2. 文本列语言是数据库建立时的默认的字符集。 3. 使用数据库默认的终止目录 stoplist.stoplist 记录存在于文本列中但不对其索 引的词。 4. 允许模糊查询。 2.3 索引参数 2.3.1DataStore 指明你的文本是如何存储的。系统默认文档储存在数据库内的文本列(CHAR, VARCHAR, VARCHAR2, BLOB, CLOB, BFILE, or XMLType)中。DataStore 对象在由过滤器处理之前从 数据库中的列摘录文本。你要索引的文档可以来自多种数据源。 Datastore Type Use When DIRECT_DATASTORE Data is stored internally in the text column. Each row is indexed as a single document. MULTI_COLUMN_DATASTORE Data is stored in a text table in more than one column. Home: http://www.itpub.net Mail: epub@itpub.net
  14. 14. ITPub 电子杂志(总第四期) 第 14 页 Datastore Type Use When Columns are concatenated to create a virtual document, one per row. DETAIL_DATASTORE Data is stored internally in the text column. Document consists of one or more rows stored in a text column in a detail table, with header information stored in a master table. FILE_DATASTORE Data is stored externally in operating system files. Filenames are stored in the text column, one per row. NESTED_DATASTORE Data is stored in a nested table. URL_DATASTORE Data is stored externally in files located on an intranet or the Internet. Uniform Resource Locators (URLs) are stored in the text column. USER_DATASTORE Documents are synthesized at index time by a user-defined stored procedure. DataStore 参数应用. 问:我有一张表记录着雇员的名称和住址,我想在这两列中查找某个单词是否存在这两个列之一。 答:方法 1,在雇员名称和住址上建立两个 ConText 索引。查询: SELECT * FROM emp WHERE contains (ename, 'biti') > 0 OR contains (address, 'biti') > 0; 方法 2, 定制 Only CTXSYS is allowed to create preferences for the MULTI_COLUMN_DATASTORE type. Any other user who attempts to create a MULTI_COLUMN_DATASTORE preference receives an error.so it run on ctxsys schema CREATE TABLE mc(id NUMBER PRIMARY KEY, NAME VARCHAR2(10), address VARCHAR2(80)) / INSERT INTO mc VALUES (1, 'John Smith', '123 Main Street biti'); EXEC ctx_ddl.create_preference('mymds', 'MULTI_COLUMN_DATASTORE'); EXEC ctx_ddl.set_attibute('mymds', 'columns', 'name, address'); Home: http://www.itpub.net Mail: epub@itpub.net
  15. 15. ITPub 电子杂志(总第四期) 第 15 页 CREATE INDEX mc_idx ON mc(NAME) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS('datastore mymds') / SELECT * FROM mc WHERE contains (name, 'biti') > 0; 问:如何实现对主/从表的全文检索? 答:使用类 Detail_DataStore。这个类经过设计,供主/从表格使用,其中大量文本存储在从表 表格列中。在进行索引之前把多个从表行联接为一个文档,使用外来关键码识别行,外键关系必 须已逻辑的方式存在,但不必作为数据库约束条件。注意在不更改主表的情况下更改从表,不会 更新索引。解决这个的办法是更新主列的值,触发索引的重新构建,或者手工设置和重新构建索 引。否则,应该存在未使用的列,来保持 SQL 语法的完整性。如下面例子中的 purchase_order 表的 line_item_body 列。 ------------------BEGIN--------------------- SET echo on DROP TABLE purchase_order; CREATE TABLE purchase_order ( id NUMBER PRIMARY KEY, description VARCHAR2(100), line_item_body CHAR(1) ) / DROP TABLE line_item; CREATE TABLE line_item ( po_id NUMBER, po_sequence NUMBER, line_item_detail VARCHAR2(1000) ) / INSERT INTO purchase_order (id, description) VALUES (1, 'Many Office Items') / INSERT INTO line_item (po_id, po_sequence, line_item_detail) VALUES (1, 1, 'Paperclips to be used for many reports') / INSERT INTO line_item (po_id, po_sequence, line_item_detail) Home: http://www.itpub.net Mail: epub@itpub.net
  16. 16. ITPub 电子杂志(总第四期) 第 16 页 VALUES (1, 2, 'Some more Oracle letterhead') / INSERT INTO line_item (po_id, po_sequence, line_item_detail) VALUES (1, 3, 'Optical mouse') / COMMIT ; BEGIN ctx_ddl.create_preference ('po_pref', 'DETAIL_DATASTORE'); ctx_ddl.set_attribute ('po_pref', 'detail_table', 'line_item'); ctx_ddl.set_attribute ('po_pref', 'detail_key', 'po_id'); ctx_ddl.set_attribute ('po_pref', 'detail_lineno', 'po_sequence'); ctx_ddl.set_attribute ('po_pref', 'detail_text', 'line_item_detail'); END; / DROP INDEX po_index; CREATE INDEX po_index ON purchase_order( line_item_body ) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS( 'datastore po_pref' ) / SELECT id FROM purchase_order WHERE contains (line_item_body, 'Oracle') > 0 / -------------------END---------------------- 2.3.2 Filter 过滤 一旦汇编了文档,它就沿管道传递。接下来这个阶段是过滤(Filter).如果文档是一种外 来格式,就将它转换为可读取的文本,以便进行索引。默认是 NULL_FILTER,它简单的直接 传递文档,不作任何修改。 通常我们使用 NULL_FILTER 过滤普通文本和 HTML 文档。下面是一个索引 HTML 文档的例子。 CREATE INDEX myindex ON docs(htmlfile) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS( 'filter ctxsys.null_filter section group ctxsys.html_section_group'); 我们使用 null_filter 过滤类和 ctxsys 用户自带的 html_section_group 区段组类。我们会在 后面马上介绍区段组(Section Groups)的概念。 2.3.2 Section Groups 区分组 Home: http://www.itpub.net Mail: epub@itpub.net
  17. 17. ITPub 电子杂志(总第四期) 第 17 页 区分组(Section Groups)是与 interMedia 一起使用 XML 的关键。这些组处理 XML(或者 HTML)文档,输出两个数据流,即区段界限和文本内容。默认是 NULL_SECTION_GROUP, 它简单的直接传递文本,不执行任何修改和处理。HTML_SECTION_GROUP 是专门用来处 理 HTML 文档的。 下面的例子中显示如何处理 HTML 文档。 ------------------BEGIN--------------------- SET echo on DROP TABLE my_html_docs; CREATE TABLE my_html_docs( id NUMBER PRIMARY KEY, html_text VARCHAR2(4000)) / INSERT INTO my_html_docs (id, html_text) VALUES (1, '<html><title>Oracle Technology</title><body>This is about the wonderful marvels of 8i and 9i</body></html>') / COMMIT ; CREATE INDEX my_html_idx ON my_html_docs( html_text )INDEXTYPE IS ctxsys.CONTEXT / -- 默认使用 NULL_SECTION_GROUP 不对文档做任何数据流处理 SELECT id FROM my_html_docs WHERE contains (html_text, 'Oracle') > 0 / -- 可以检索到区段界限之间的文本 SELECT id FROM my_html_docs WHERE contains (html_text, 'title') > 0 / SELECT id FROM my_html_docs WHERE contains (html_text, 'html') > 0 Home: http://www.itpub.net Mail: epub@itpub.net
  18. 18. ITPub 电子杂志(总第四期) 第 18 页 / /* 也可以检索到 区段界限内的文本。但由于 HTML 文件中的一些标记如<b> <body> <A href=…..>等对我们没有提供有用的信息。而且在索引中还浪费了空间和 CPU。因此 HTML 标记 不应该被索引 */ --我们可以定制我们自己的区段标记。可以查询在某个区段出现的单词 BEGIN ctx_ddl.create_section_group ('my_section_group', 'BASIC_SECTION_GROUP'); ctx_ddl.add_field_section ( group_name=> 'my_section_group', section_name=> 'Title', tag => 'title', visible=> FALSE ); END; / DROP INDEX my_html_idx; CREATE INDEX my_html_idx ON my_html_docs( html_text ) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS( 'section group my_section_group' ) / SELECT id FROM my_html_docs WHERE contains (html_text, 'Oracle within title') > 0; ------------------END--------------------- 下面是如何检索 XML 文档的例子 InterMedia Text 支持索引 XML 文档通过指定区段组。区段组就是 XML 文档中预先定义的节点. 你可以用 WithIn 在指定检索某个节点,提高了检索的准确性。 1) 首先,创建一个表来存储我们的 XML 文档: CREATE TABLE employee_xml( id NUMBER PRIMARY KEY, xmldoc CLOB ) / Home: http://www.itpub.net Mail: epub@itpub.net
  19. 19. ITPub 电子杂志(总第四期) 第 19 页 2) 插入一个简单的文档(the DTD is not required) INSERT INTO employee_xml VALUES (1, '<?xml version="1.0"?> <!DOCTYPE employee [ <!ELEMENT employee (Name, Dept, Title)> <!ELEMENT Name (#PCDATA)> <!ELEMENT Dept (#PCDATA)> <!ELEMENT Title (#PCDATA)> ]> <employee> <Name>Joel Kallman</Name> <Dept>Oracle Service Industries Technology Group</Dept> <Title>Technologist</Title> </employee>'); 3)创建一个叫'xmlgroup'的 interMedia Text section group , 添加 Name 和 Dept tag 到 section group 中。(Caution: in XML, tag names are case-sensitive, but tag names in section groups are case-insensitive) BEGIN ctx_ddl.create_section_group ('xmlgroup', 'XML_SECTION_GROUP'); ctx_ddl.add_zone_section ('xmlgroup', 'Name', 'Name'); ctx_ddl.add_zone_section ('xmlgroup', 'Dept', 'Dept'); END; 4)Create our interMedia Text index, specifying the section group we created above. Also, specify the null_filter, as the Inso filter is not required. CREATE INDEX employee_xml_index ON employee_xml( xmldoc ) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS( 'filter ctxsys.null_filter section group xmlgroup' ) / 5) 现在,执行一个查询,搜寻特定 Section 中的 Name: SELECT id FROM employee_xml WHERE contains (xmldoc, 'Joel within Name') > 0; 6)Only non-empty tags will be indexed, but not the tag names themselves. Thus, the following queries will return zero rows. Home: http://www.itpub.net Mail: epub@itpub.net
  20. 20. ITPub 电子杂志(总第四期) 第 20 页 SELECT id FROM employee_xml WHERE contains (xmldoc, 'title') > 0; SELECT id FROM employee_xml WHERE contains (xmldoc, 'employee') > 0; 7) But the following query will locate our document, even though we have not defined Title as a section. SELECT id FROM employee_xml WHERE contains (xmldoc, 'Technologist') > 0; Let's say you want to get going right away with indexing XML, and don't want to have to specify sections for every element in your XML document collection. You can do this very easily by using the predefined AUTO_SECTION_GROUP. This section group is exactly like the XML section group, but the pre-definition of sections is not required. For all non-empty tags in your document, a zone section will be created with the section name the same as the tag name. Use of the AUTO_SECTION_GROUP is also ideal when you may not know in advance all of the tag names that will be a part of your XML document set. 8) Drop our existing interMedia Text index. 9)And this time, recreate it specifying the AUTO_SECTION_GROUP. We do not need to predefine the sections of our group, it is handled for us Automatically. DROP INDEX employee_xml_index / CREATE INDEX employee_xml_index ON employee_xml( xmldoc ) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS( 'filter ctxsys.null_filter section group ctxsys.auto_section_group' ) / 10) 再一次,我们使用 Section 查找定位我们的文档: SELECT id FROM employee_xml WHERE contains (xmldoc, 'Technologist within Title') > 0; Home: http://www.itpub.net Mail: epub@itpub.net
  21. 21. ITPub 电子杂志(总第四期) 第 21 页 2.3.3 Storage 类 Storage(存储空间)组的类只含有 BASIC_STORAGE.默认情况下,BASIC_STORAGE 对象的 属性是空的。 我们通常需要定制自己的 STORAGE 类, 来控制索引的存储参数以及存储空间。 建立全文索引的时候我们通常会考虑表段 dr$indexname$I,,dr$indexname$R,索引段 dr$indexname$X 的空间分配。 类型 描述 BASIC_STORAGE 为 CONTEXT 索引指定默认的存储参数 BASIC_STORAGE 有如下参数 属性 属性值 i_table_clause Parameter clause for dr$indexname$I table creation. Specify storage and tablespace clauses to add to the end of the internal CREATE TABLE statement. The I table is the index data table. k_table_clause Parameter clause for dr$indexname$K table creation. Specify storage and tablespace clauses to add to the end of the internal CREATE TABLE statement. The K table is the keymap table. r_table_clause Parameter clause for dr$indexname$R table creation. Specify storage and tablespace clauses to add to the end of the internal CREATE TABLE statement. The R table is the rowid table. The default clause is: 'LOB(DATA) STORE AS (CACHE)' n_table_clause Parameter clause for dr$indexname$N table creation. Specify storage and tablespace clauses to add to the end of the internal CREATE TABLE statement. The N table is the negative list table. i_index_clause Parameter clause for dr$indexname$X index creation. Specify storage and tablespace clauses to add to the end of the internal CREATE INDEX statement. The default clause is: 'COMPRESS 2' which instructs Oracle to compress this index table. If you choose to override the default, Oracle recommends including COMPRESS 2 in your parameter clause to compress this table, since such Home: http://www.itpub.net Mail: epub@itpub.net
  22. 22. ITPub 电子杂志(总第四期) 第 22 页 属性 属性值 compression saves disk space and helps query performance. p_table_clause Parameter clause for the substring index if you have enabled SUBSTRING_INDEX in the BASIC_WORDLIST. Specify storage and tablespace clauses to add to the end of the internal CREATE INDEX statement. The P table is an index-organized table so the storage clause you specify must be appropriate to this type of table. 默认情况下,4 个表段和 1 个索引段将会建立在拥有该表的用户的默认表空间下。如下: CREATE INDEX iowner.idx ON towner.tab(b) INDEXTYPE IS ctxsys.CONTEXT; 索引将会建立在 IOWNER 用户的默认表空间下,而不管发出该语句的用户是否是 IOWNER。 Storage 范例 下面我们自己定制 CONTEXT 索引的存储选项。可以为各个段指定不同的表空间。 EXECUTE ctx_ddl.drop_preference('mystore'); BEGIN ctx_ddl.create_preference ('mystore', 'BASIC_STORAGE'); ctx_ddl.set_attribute ('mystore', 'I_TABLE_CLAUSE', 'tablespace indx '); ctx_ddl.set_attribute ( 'mystore', 'I_INDEX_CLAUSE', 'tablespace users03 compress 2 ' ); END; --ORACLE 推荐 DR$INDX$X 进行压缩 COMPRESS 2 CREATE INDEX html1_idx ON html1(newsdescription) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS('storage mystore'); ---查看段的存储参数,这样方便了以后数据容量的扩展。 SELECT segment_name, tablespace_name FROM user_segments WHERE segment_name LIKE '%HTML1%'; 2.3.4 设置词法分析器(lexer) Home: http://www.itpub.net Mail: epub@itpub.net
  23. 23. ITPub 电子杂志(总第四期) 第 23 页 Oracle 实现全文检索,其机制其实很简单。即通过 Oracle 专利的词法分析器(lexer),将文章 中所有的表意单元(Oracle 称为 term)找出来,记录在一组 以 dr$开头的表中,同时记下 该 term 出现的位置、次数、hash 值等信息。检索时,Oracle 从这组表中查找相应的 term, 并计算其出现频率, 根据某个算法来计算每个文档的得分 (score),即所谓的‘匹配率’。 lexer 而 则是该机制的核心, 它决定了全文检索的效率。 Oracle 针对不同的语言提供了不同的 lexer, 而我们通常能用到其中的三个: basic_lexer: 针对英语。它能根据空格和标点来将英语单词从句子中分离,还能自动将 一些出现频率过高已经失去检索意义的单词作为‘垃圾’处理,如 if , is 等,具有较高的处 理效率。但该 lexer 应用于汉语则有很多问题,由于它只认空格和标点,而汉语的一句 话中通常不会有空格,因此,它会把整句话作为一个 term,事实上失去检索能力。以‘中 国人民站起来了’这句话为例,basic_lexer 分析的结果只有一个 term ,就是‘中国人民站 起来了’。此时若检索‘中国’,将检索不到内容。 chinese_vgram_lexer: 专门的汉语分析器,支持所有汉字字符集(ZHS16CGB231280 ZHS16GBK ZHT32EUC ZHT16BIG5 ZHT32TRIS ZHT16MSWIN950 ZHT16HKSCS UTF8 )。该分析器按字为单元来分析汉语句子。‘中国人民站起来了’这句话,会被它分 析成如下几个 term: ‘中’,‘中国’,‘国人’,‘人民’,‘民站’,‘站起’,起来’,‘来了’,‘了’。 可以看出,这种分析方法,实现算法很简单,并且能实现‘一网打尽’,但效率则是差强 人意。 chinese_lexer: 这是一个新的汉语分析器,只支持 utf8 字符集。上面已经看到,chinese vgram lexer 这个分析器由于不认识常用的汉语词汇,因此分析的单元非常机械,像上 面的‘民站’,‘站起’在汉语中根本不会单独出现,因此这种 term 是没有意义的,反而影 响效率。chinese_lexer 的最大改进就是该分析器 能认识大部分常用汉语词汇,因此能 更有效率地分析句子,像以上两个愚蠢的单元将不会再出现,极大 提高了效率。但是 它只支持 utf8, 如果你的数据库是 zhs16gbk 字符集,则只能使用笨笨的那个 Chinese vgram lexer. 如果不做任何设置,Oracle 缺省使用 basic_lexer 这个分析器。要指定使用哪一个 lexer, 可 以这样操作: 第一. 在 ctxsys 用户下建立一个 preference: BEGIN ctx_ddl.create_preference ('my_lexer', 'chinese_vgram_lexer'); END; 第二. 在建立 intermedia 索引时,指明所用的 lexer: CREATE INDEX myindex ON mytable(mycolumn) indextype is ctxsys.context parameters('lexer my_lexer'); Home: http://www.itpub.net Mail: epub@itpub.net
  24. 24. ITPub 电子杂志(总第四期) 第 24 页 这样建立的全文检索索引,就会使用 chinese_vgram_lexer 作为分析器。 相应的,索引中 文就比索引英文占用的表空间多了许多。Oracle Text 为了性能不得不牺牲了空间。如下是 我的简单存储空间测试: 文本数据量 索引数据量(4 个表段和 1 个索引段) 6M 80M 80M 900M 230M 2880M 1344M 15232M 2.3.5 STOP Lists 类 Stop List 只不过是被索引忽略的单词的列表。这些通常是常见的单词,正常情况下不会以任 何方式查询它们,因此,索引它们纯粹是表格空间和处理器周期的浪费。在具体的应用中, 可能存在这样的单词,它们在特定的文集中出现的频率太大,无法提供有意义的内容,特别 是常用的单词。 Stop List 可以含有最多 4095 个单词,每个单词最多 64 个字符,同时为英语和其它语言提 供了默认列表。 下图是 Chinese Stoplist (Simplified)的默认列表: 你可以查看英文的默认列表: SELECT spw_word FROM DR$STOPWORD; 你可以查询 ctx_stoplists 和 ctx_stopwords 视图来观察这些语言。 EXECUTE ctx_ddl.create_stoplist('stoppref'); SELECT * FROM ctx_stoplists; Home: http://www.itpub.net Mail: epub@itpub.net
  25. 25. ITPub 电子杂志(总第四期) 第 25 页 SPL_OWNER SPL_NAME SPL_COUNT SPL_TYPE CTXSYS STOPPREF 0 BASIC_STOPLIST EXECUTE ctx_ddl.add_stopword('stoppref','的'); SELECT * FROM ctx_stoplists; SPL_OWNER SPL_NAME SPL_COUNT SPL_TYPE CTXSYS STOPPREF 1 BASIC_STOPLIST SELECT spw_word FROM dr$stopword; 2.3.5 Lists 类 要考虑的最后一个类是单一的 Word List 类,即 BASIC_WORDLIST。创建索引时不使用这 个类,这个类只在某些高级形式的查询中使用。茎干查询使用从 Xerox 公司许可的技术,来 匹配单词与通用的语言根。 2.3.6 其它选项 MEMORY 参数以通常的方式附着到 CREATE INDEX 中的 PARAMETERS 上,设置用于构建或 更改索引的内存量。这个量不能超过 MAX_INDEX_MEMEORY, 使用 CTX_ADM.SET_PARAMETER 对其进行设置。 查看系统默认参数项: SELECT par_name, par_value FROM ctx_parameters; 设置系统默认参数: CTX_ADM.SET_PARAMETER(param_name IN VARCHAR2, param_value IN VARCHAR2); Oracle Text 使用的索引机制比通常的 ORACLE B-TREE 索引更复杂,且文档实际是在内存中 构建的,而不是一次一行的添加到 B-TREE。到达内存参数指定的值时,更新磁盘山的索引, 接着,缓冲区由下一组文档重用。任一时刻缓冲区内的文档数会有所不同,并且在索引处理 之前不进行任何排序。因此,在少量的内存中索引大量文档会导致出现碎片索引情况。 3 索引维护 Home: http://www.itpub.net Mail: epub@itpub.net
  26. 26. ITPub 电子杂志(总第四期) 第 26 页 这节讲一下当索引操作失败的时候所要进行的一些处理。 3.1 查看索引错误 有时候,索引操作可能失败或者没有成功结束。当发生错误的时候,它会将错误记录在系统 表中。 你可以查看某个用户下 TEXT 索引发生的错误 CTX_USER_INDEX_ERRORS;也可以查询 CTXSYS. CTX_INDEX_ERRORS.查看全部用户的索引错误。 查看最近发生的错误: SELECT err_timestamp, err_text FROM ctx_user_index_errors ORDER BY err_timestamp DESC; 清除错误视图: DELETE FROM ctx_user_index_errors; 3.2 删除索引 例如,删除索引名称为 newindex 的索引。 DROP INDEX newsindex; 如果 Oracle 不能决定索引的状态,例如建立索引的时候发生错误,没有成功结束,则需要 强制删除索引。 DROP INDEX newsindex FORCE; 3.3 索引重建 使用 ALTER INDEX 重建索引。你可能需要用新的参数重新建立索引。例如可能想用新的词 法分析器替换索引现有的: ALTER INDEX newsindex REBUILD PARAMETERS('replace lexer my_lexer'); 3.4 删除自定义参数 如果你不再需要某个自定义参数,你可以使用 CTX_DDL.DROP_PREFERENCE 删除它。例如 参数自定义参数 my_lexer。 Home: http://www.itpub.net Mail: epub@itpub.net
  27. 27. ITPub 电子杂志(总第四期) 第 27 页 BEGIN ctx_ddl.drop_preference ('my_lexer'); END; 4 管理 DML 操作 对于 CTXSYS.CONTEXT 索引,当应用程序对基表进行 DML 操作后,对基表的索引维护是必 须的。索引维护包括索引同步和索引优化。 在索引建好后,我们可以在该用户下查到 Oracle 自动产生了以下几个表:(假设索引名为 myindex): DR$myindex$I、DR$myindex$K、DR$myindex$R、DR$myindex$N 其中以 I 表最重要,可 以查询一下该表,看看有什么内容: SELECT token_text, token_count FROM dr$i_rsk1$I WHERE ROWNUM <= 20; 这里就不列出查询接过了。可以看到,该表中保存的其实就是 Oracle 分析你的文档后,生 成的 term 记录在这里,包括 term 出现的位置、次数、hash 值等。当文档的内容改变后, 可以想见这个 I 表的内容也应该相应改变,才能保证 Oracle 在做全文检索时正确检索到内 容(因为所谓全文检索,其实核心就是查询这个表) 。那么如何维护该表的内容呢?总不能 每次数据改变都重新建立索引吧!这就用到 sync 和 optimize 了。 同步(sync): 将新的 term 保存到 I 表; 优化(optimize): 清除 I 表的垃圾,主要是将已经被删除的 term 从 I 表删除。 当基表中的被索引文档发生 insert、update、delete 操作的时候,基表的改变并不能马上影 响到索引上直到同步索引。可以查询视图 CTX_USER_PENDING 查看相应的改动。例如: SELECT pnd_index_name, pnd_rowid, TO_CHAR (pnd_timestamp, 'dd-mon-yyyy hh24:mi:ss') timestamp FROM ctx_user_pending; 该语句的输出类似如下: PND_INDEX_NAME PND_ROWID TIMESTAMP ------------------------------ ------------------ -------------------- MYINDEX AAADXnAABAAAS3SAAC 06-oct-1999 15:56:50 同步和优化方法: 可以使用 Oracle 提供的 ctx_ddl 包同步和优化索引。 Home: http://www.itpub.net Mail: epub@itpub.net
  28. 28. ITPub 电子杂志(总第四期) 第 28 页 对于 CTXCAT 类型的索引来说, 当对基表进行 DML 操作的时候,Oracle 自动维护索引。对 文档的改变马上反映到索引中。CTXCAT 是事务形的索引。 4.1 索引同步 4.1.1CTXSRV(同步进程) Oracle 提供一个全文索引同步服务进程负责监视索引表变动并且第一时间同步索引。 只需要在后台运行这个进程,它会监视数据的变化,及时进行同步。但由于存在一些问题在 未来的 ORACLE 版本中将要被取代。 启动同步索引服务进程方法: HOST ctxsrv -user ctxsys/ctxsys>&/tmp/ctx.log& 当你启动了 CTXSRV 服务进程,在后台的同步请求处理就会象事时一样,在你提交修改 1, 2 秒后新的数据马上就被索引了。 与手工同步相比,自动索引同步更容易使索引变的稀疏,需要执行 DBMS_JOB 定期优化和 重建索引 rebuild parameters( 'sync' )。 默认情况下,如果你不启动 CTXSRV 进程, 索引不会自动更新除非你手工告诉它们去更新自 己。你可以使用 alter index <iname> rebuild parameters ('sync') 更新索引。 ALTER INDEX search_idx REBUILD parameters( 'sync' ) / Index altered. 9i 提供了新的专门用于更新索引的包 ctx_ddl.sync_index(…) 4.1.2 CTX_DDL.SYNC_INDEX 在对基表插入,修改,删除之后同步索引。推荐使用 sync 同步索引。 语法: ctx_ddl.sync_index( idx_name IN VARCHAR2 DEFAULT NULL memory IN VARCHAR2 DEFAULT NULL, part_name IN VARCHAR2 DEFAULT NULL parallel_degree IN NUMBER DEFAULT 1); Home: http://www.itpub.net Mail: epub@itpub.net
  29. 29. ITPub 电子杂志(总第四期) 第 29 页 idx_name 索引名称 memory 指定同步索引需要的内存。默认是系统参数 DEFAULT_INDEX_MEMORY 。 指定一个大的内存时候可以加快索引效率和查询速度,且索引有较少的碎片 part_name 同步哪个分区索引。 parallel_degree 并行同步索引。设置并行度。 例如: 使用 2M 内存同步索引 myindex: BEGIN ctx_ddl.sync_index ('myindex', '2M'); END; NOTE:执行者必须是索引所有者或者 CTXSYS 用户。如果执行者是 CTXSYS 用户,索引名称可 以是空 NULL,这样默认优化全部的 CONTEXT 索引。这样的同步效果就如同 ctxsrv. 我们推荐定 期执行作业 job 同步索引。-- 为每一个索引制定单独的作业 job, 一个 ctxsys 作业 job 同步全 部索引。这样就减少了使用 ctxsrv 的机率,也不用在每次数据库启动后都要启动 CTXSRV 服务 进程。由于 CTXSRV 有一些缺陷,在未来将不再会被 ORACLE 使用或者被取代。 INSERT INTO mytable VALUES (2, 'first,second.this is the second rows before indexed'); COMMIT ; EXEC ctx_ddl.sync_index('mytable_idx'); SELECT /*+ FIRST_ROWS() */ ID, SCORE(1), TEXT FROM MYTABLE WHERE CONTAINS (TEXT, 'searchterm', 1) > 0 ORDER BY SCORE(1) DESC; 其中 score(1)为 Oracle 为全文查询计算的主题符合程度。 4.2 索引优化 经常的索引同步将会导致你的 CONTEXT 索引产生碎片。索引碎片严重的影响了查询的反应 速度。你可以定期优化索引来减少碎片,减少索引大小,提高查询效率。为了更好的理解索 引优化,我们先看看索引的结构以及碎片是如何产生的。 CONTEXT 索引是反向索引,每一个索引项目都包括单词和这个单词所出现过的文档地址。 例如在一个初始化索引过程中,单词 DOG 可以包括如下条目 DOG DOC1 DOC3 DOC5 Home: http://www.itpub.net Mail: epub@itpub.net
  30. 30. ITPub 电子杂志(总第四期) 第 30 页 当新的文档被包含到表的时候,索引被同步。如果新行 DOC7 也包括单词 DOG,将会形成 如下条目。 DOG DOC1 DOC3 DOC5 DOG DOC7 很多的 DML 操作以后,单词 DOG 的条目可能如下情况: DOG DOC1 DOC3 DOC5 DOG DOC7 DOG DOC9 DOG DOC11 同步新增加的文档产生了索引碎片。单词 DOG 的文挡列表会越来越长,索引越来越大。 你可以优化索引(CTX_DDL.OPTIMIZE_INDEX),使用 FULL 或者 FAST 参数都可以降低索 引碎片,提高索引效率。 4.2.1 文档垃圾处理 当文本从表中删除的时候,Oracle Text 标记删除的文档,但是并不马上修改索引。因此, 就的文档信息占据了不必要的空间, 导致了查询额外的开销。 你必须以 FULL 模式优化索引, 从索引中删除无效的旧的信息。 这个过程叫做垃圾处理。 当你经常的对表文本数据进行更新, 删除操作的时候,垃圾处理是很必要的。 BEGIN ctx_ddl.optimize_index ('myidx', 'full'); END; 4.2.2 Single Token Optimization 除了优化整个索引以外,你还可以专门对某个标记(token)进行优化。你可以仅仅优化那 些经常查询的标记(token),而不必花太多时间在很少查询的单词上。 例如,你可以专门优化 token DOG,它经常被检索或者经常被更新。这样可以提高查询这个 token 的查询效率。 BEGIN ctx_ddl.optimize_index ('myidx', 'token', token => 'DOG'); END; 4.2.3 FAST MODE 这种方法仅仅使碎片行紧凑。但是,旧的数据并不从索引中删除。 BEGIN Home: http://www.itpub.net Mail: epub@itpub.net
  31. 31. ITPub 电子杂志(总第四期) 第 31 页 ctx_ddl.optimize_index ('myidx', 'fast'); END; 4.2.4 使用 job 定时同步和优化 用以下的两个 job 来完成(该 job 要建在和表同一个用户下) : -- sync: VARIABLE jobno number; BEGIN DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.sync_index(''myindex'');', SYSDATE, 'SYSDATE + (1/24/4)'); commit; END; -- optimizer VARIABLE jobno number; BEGIN DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.optimize_index(''myindex'',''FULL'');', SYSDATE, 'SYSDATE + 1'); commit; END; 其中,第一个 job 的 SYSDATE + (1/24/4)是指每隔 15 分钟同步一次,第二个 job 的 SYSDATE + 1 是每隔 1 天做一次全优化。 具体的时间间隔, 你可以根据自己的应用的需要而定。 至此, 你的全文检索功能已设置完成。 5 检索 CONTAINS 你建立好 CONTEXT 索引后,可以使用 CONTAINS 操作符检索数据了。你可以有很多查询选 项。你可以进行逻辑,模糊,通配符,主题等查询,还可以查询 HTML 和 XML 文档。 5.1 简单例子 SQL: SELECT 语句中,可以在 WHERE 指定 CONTAINS 操作符。还可以指定返回记录的得分(SCORE)。 SELECT score (1) title FROM news Home: http://www.itpub.net Mail: epub@itpub.net
  32. 32. ITPub 电子杂志(总第四期) 第 32 页 WHERE contains (text, 'Oracle', 1) > 0; 得分 SCORE 是指查询结果的贴切程度。得分越高表示查询信息满意度越高。你可以根据 SCORE 进行排序。 SELECT score (1), title FROM news WHERE contains (text, 'Oracle', 1) > 0 ORDER BY score (1) DESC; SELECT score (1), title, issue_date FROM news WHERE contains (text, 'Oracle', 1) > 0 AND issue_date >= ('01-OCT-97') ORDER BY score (1) DESC; A structured query, also called a mixed query。For example, the upper SELECT statement returns all articles that contain the word Oracle that were written on or after October 1, 1997. SELECT id,score(1),score (2),score (1)+ score (2) total, text FROM mytable WHERE contains (text, 'biti', 1) > 0 OR contains (text, 'hello', 2) > 0 ORDER BY total DESC; 根据 contains 中的不同数字标示各个 contains 返回的分数 Score。 PL/SQL 形式: DECLARE rowno NUMBER := 0; BEGIN FOR c1 IN ( SELECT score (1) score, title FROM news WHERE contains (text, 'Oracle', 1) > 0 ORDER BY score (1) DESC) LOOP rowno := rowno + 1; DBMS_OUTPUT.put_line ( c1.title || ': ' || c1.score); EXIT WHEN rowno = 10; END LOOP; END; Home: http://www.itpub.net Mail: epub@itpub.net
  33. 33. ITPub 电子杂志(总第四期) 第 33 页 返回了得分最高的前 10 条记录. 5.2 Logical Operators 允许你组合搜索条件,通过使用 AND,OR 等逻辑。 操作符 符号 描述 例子表达式 AND & Use the AND operator to search 'cats AND dogs' for documents that contain at 'cats & dogs' least one occurrence of each of the query terms. Score returned is the minimum of the operands. OR | Use the OR operator to search 'cats | dogs' for documents that contain at 'cats OR dogs' least one occurrence of any of the query terms. Score returned is the maximum of the operands. NOT ~ Use the NOT operator to search To obtain the documents that for documents that contain one contain the term animals but not query term and not another. dogs, use the following expression: 'animals ~ dogs' ACCUM , Use the ACCUM operator to The following query returns all search for documents that documents that contain the terms contain at least one occurrence dogs, cats and puppies giving the of any of the query terms. The highest scores to the documents accumulate operator ranks that contain all three terms: documents according to the total term weight of a 'dogs, cats, puppies' document. EQUIV = Use the EQUIV operator to The following example returns all specify an acceptable documents that contain either the substitution for a word in a phrase alsatians are big dogs or query. German shepherds are big dogs: 'German Home: http://www.itpub.net Mail: epub@itpub.net
  34. 34. ITPub 电子杂志(总第四期) 第 34 页 操作符 符号 描述 例子表达式 shepherds=alsatians are big dogs' 在 Oracle Text Reference Release 9.2 可以查看更多的选项。 5.3 如何优化查询 5.3.1 收集统计信息 By collecting statistics on the Text domain index, the Oracle cost-based optimizer is able to do the following: • estimate the selectivity of the CONTAINS predicate • estimate the I/O and CPU costs of using the Text index, that is, the cost of processing the CONTAINS predicate using the domain index • estimate the I/O and CPU costs of each invocation of CONTAINS 5.3.2 使用 FIRST_ROWS(n) for ORDER BY Queries With the FIRST_ROWS hint, Oracle instructs the Text index to return rowids in score-sorted order, if possible. Without the hint, Oracle sorts the rowids after the Text index has returned all the rows in unsorted order that satisfy the CONTAINS predicate. Retrieving the entire result set as such takes time. Since only the first 10 hits are needed in this query, using the hint results in better performance. Note: Use the FIRST_ROWS(n) hint when you need only the first few hits of a query. When you need the entire result set, do not use this hint as it might result in poor performance. 6.分区 Home: http://www.itpub.net Mail: epub@itpub.net
  35. 35. ITPub 电子杂志(总第四期) 第 35 页 CONTEXT 索引支持在分区表山建立本地分区索引,但仍然有一些限制。如下: 分区表必须是按范围分区,不支持 HASH 分区和复合分区。 你应该为每个分区指定索引分区名称。 如果不指定, 系统默认为每个分区表指 定。分区索引列表的顺序必须和分区表的顺序一致。 可以为每个分区分别指定 PRAMETERS 参数,但是 PARAMETERS 只允许包括 STORAGE 和 MEMEROY 参数。 不能指定 ONLINE 建立索引。 可以查询 CTX_INDEX_PARTITIONS 或者 CTX_USER_INDEX_PARTITIONS 获得更多信息。 6.1 创建一个本地分区索引: ------------------------BEGIN--------------------------- PROMPT create partitioned table and populate it CREATE TABLE part_tab (a int, b varchar2(40)) PARTITION BY RANGE(a) (partition p_tab1 values less than (10), partition p_tab2 values less than (20), partition p_tab3 values less than (30)); PROMPT create customer storage preference assigned each partition Execute ctx_ddl.drop_preference('mystore1'); BEGIN ctx_ddl.create_preference ('mystore1', 'BASIC_STORAGE'); ctx_ddl.set_attribute ('mystore1', 'I_TABLE_CLAUSE', 'tablespace indx '); ctx_ddl.set_attribute ( 'mystore1', 'I_INDEX_CLAUSE', 'tablespace users03 compress 2 ' ); END; PROMPT create partitioned index CREATE INDEX part_idx on part_tab(b) INDEXTYPE IS CTXSYS.CONTEXT LOCAL (partition p_idx1 parameters(‘storage mystore1’), partition p_idx2 parameters(‘storage mystore2’), partition p_idx3 parameters(‘storage mystore3’)); -------------------------END---------------------------- Home: http://www.itpub.net Mail: epub@itpub.net
  36. 36. ITPub 电子杂志(总第四期) 第 36 页 6.2 并行的创建一个本地分区索引 可以并行的建立分区索引,加快建立索引速度。但是建立索引不能“一步到位“。我们必须 先建立一个 unusable 索引,然后利 DBMS_PCLXUTIL.BUILD_PART_INDEX 并行建立索引。 ------------------------BEGIN--------------------------- PROMPT the base table has three partitions. PROMPT We create a local partitioned unusable index first CREATE INDEX tdrbip02bx ON tdrbip02b(text) indextype is ctxsys.context local (partition tdrbip02bx1, partition tdrbip02bx2, partition tdrbip02bx3) unusable; PROMPT run the DBMS_PCLUTIL.BUILD_PART_INDEX,which builds the 3 partitions in parallel (inter-partition parallelism). Also inside each partition, index creation is done in parallel (intra-partition parallelism) with a parallel degree of 2. BEGIN DBMS_PCLXUTIL.build_part_index (3, 2, 'TDRBIP02B', 'TDRBIP02BX', TRUE); END; -------------------------END---------------------------- 6.3 查询分区索引 你可以在单个表分区上进行全文检索。 SELECT * FROM part_tab PARTITION (p_tab4) WHERE contains (b, 'Oracle') > 0 ORDER BY score; 7.Oracle Text 支持对本地文件的检索 它的实现是依靠参数 datastore 和 filter 的组合。在数据库的文本列中只保存指向硬盘文件 的指针。建立索引的时候,Oracle 读取硬盘上的文件并且将索引存储在 Oracle 数据库中。 Oracle 支持对很多格式的文件的文本检索,包括文本文件 Txt, Html 文件, Word 文档, Excel 表格, PowerPoint 的文本检索,也支持 PDF(pdf 版本 1.4 目前还不支持)。 Home: http://www.itpub.net Mail: epub@itpub.net
  37. 37. ITPub 电子杂志(总第四期) 第 37 页 而且配合 Lexer 参数很好的支持了中文字符集的检索。 具体实现方法: 首先,建立存储选项参数。制定 DATASTORE 参数为 FILE_DATASTROE,提示 Oracle 从文 件路径中索引文本。 然后制定 path 参数,你可以指定多个文件存储的文件路径 ,windows 环境用”;”号间隔 (Path1;Path2;Path3;;), Unix 环境用“:”号间隔(Path1:Path2:Path3::) BEGIN ctx_ddl.create_preference ('my_datastore_prefs', 'FILE_DATASTORE'); ctx_ddl.set_attribute ('my_datastore_prefs', 'path', 'c:TEMP'); END; 下一步,建立保存这些文件名称的表。Id 列是主键,title 列是对文本的简单说明,thefile 列保存着磁盘中 Path 目录下文件的名称。文件必须能够在 Path 路径下找到,否则 Oracle 会报文件无法访问的错误信息。 然后向表中插入数据,注意:thefile 列保存的必须是服务器上的指定的 Path 路径下面的文 件。 CREATE TABLE mydocs( id NUMBER PRIMARY KEY, title VARCHAR2(255), thefile VARCHAR2(255) ); INSERT INTO mydocs( id, title, thefile ) VALUES( 1, 'Document1', 'WordDoc1.doc'); INSERT INTO mydocs( id, title, thefile ) VALUES( 2, 'Document2', 'WordDoc2.doc'); INSERT INTO mydocs( id, title, thefile ) VALUES( 3, 'Document3', 'WordDoc3.doc'); COMMIT; 建立全文索引,使用参数 Datastore 和 Filter,Lexer 。 Filter 可以帮助 Oracle 识别不同格式 文件,可以是文本文件,Word 文档,Pdf 文档等。Lexer 用来保证可以很好的从文件中索引 中文信息。 CREATE INDEX mydocs_text_index ON mydocs(thefile) INDEXTYPE IS ctxsys.context PARAMETERS('datastore my_datastore_prefs Filter ctxsys.info_filter Lexer my_lexer'); -- -- 测试是否索引文件成功 -- SELECT id,title FROM mydocs WHERE contains( thefile, '你好' ) > 0; Home: http://www.itpub.net Mail: epub@itpub.net
  38. 38. ITPub 电子杂志(总第四期) 第 38 页 指定路径带来的相关问题: 如 CTX_DDL.SET_ATTRIBUTE( 'my_datastore_prefs', 'path', 'c:TEMP;c:docs' ); 如果在 2 个目录中均有同名的文件 1.doc, 如果在 thefile 列中保存的仅仅是文件名称 1.doc, 则 Oracle 顺序查找路径下的文件,这样就会索引 2 次在 C:TEMP 下的文件 1.doc. 我们可 以通过加上文件的路径信息。 在维护文档修改的时候同步索引的问题: 如果你修改了路径下面的某个文件的内容,加入了文本或者删除了文本,Oracle 在同步的时 候不会察觉到文档的内容的修改。有一个方法可以保证同步: 修改了内容之后,更新一下表 thefile 的信息,但仍保证文本路径不变。 UPDATE mydocs SET thefile = 'c:source.doc' WHERE thefile = 'c:source.dco'; 再次执行同步索引的时候,Oracle 才会保持文档内容同步。 关于建立以及同步索引的时候发生的错误信息可以从 ctx_user_index_errors 用户视图 中查看。 8.Oracle Text 支持检索对网页的文本检索 通过在表里面存储网络上各种格式的文本文件,HTML 文件的路径 Url。Oracle 在建立索引 的时候,可以顺着 Url 读取文件的流信息,并且将索引存储在磁盘上。这样通过本地查找索 引可以获得有用的网页的 Url。 通过自定义 Datastore 选项,指定 URL_DATASTORE 类型。它支持 Http 访问,和 Ftp 访问, 本地文件系统的访问。 存储在文本列中的 Url 格式如下: [URL:]<access_scheme>://<host_name>[:<port_number>]/[<url_path>] access_scheme 字符串可以是 ftp、 http 或者 file. 例如: http://mymachine.us.Oracle.com/home.html ――――――――――――――――――――――――――― 注: login:password@ 格式的语法只有在 Ftp 访问形式下才有效 ――――――――――――――――――――――――――― Home: http://www.itpub.net Mail: epub@itpub.net
  39. 39. ITPub 电子杂志(总第四期) 第 39 页 URL_DATASTORE 参数 URL_DATASTORE 的一些参数,其中 timeout,proxy 是经常用到的: 属性 属性值 timeout Specify the timeout in seconds. The valid range is 15 to 3600 seconds. The default is 30.这个参数根据网络性能调整。 maxthreads Specify the maximum number of threads that can be running simultaneously. Use a number between 1and 1024. The default is 8. Urlsize Specify the maximum length of URL string in bytes. Use a number between 32 and 65535. The default is 256. maxurls Specify maximum size of URL buffer. Use a number between 32 and 65535. The defaults is 256. maxdocsize Specify the maximum document size. Use a number between 256 and 2,147,483,647 bytes (2 gigabytes). The defaults is 2,000,000. http_proxy Specify the host name of http proxy server. Optionally specify port number with a colon in the form hostname:port ftp_proxy Specify the host name of ftp proxy server. Optionally specify port number with a colon in the form hostname:port. no_proxy Specify the domain for no proxy server. Use a comma separated string of up to 16 domain names. 索引建立过程: 首先建立自己的 URL_DATASTORE 选项。如下指定了代理,Timeout 时间。 BEGIN ctx_ddl.create_preference ('URL_PREF', 'URL_DATASTORE'); ctx_ddl.set_attribute ('URL_PREF', 'Timeout', '300'); END; 建立存储 Url 路径的表: CREATE TABLE urls(id NUMBER PRIMARY KEY, url VARCHAR2(2000)); INSERT INTO urls VALUES (1, 'http:// http://intranet-center/'); INSERT INTO urls VALUES (2, 'http://founderweb:9080/default.jsp'); COMMIT ; Home: http://www.itpub.net Mail: epub@itpub.net
  40. 40. ITPub 电子杂志(总第四期) 第 40 页 建立索引,索引 Html 文件可以使用 HTML_SECTION_GROUP: CREATE INDEX datastores_text ON urls ( url ) INDEXTYPE IS ctxsys.CONTEXT PARAMETERS ( 'Datastore URL_PREF Lexer my_lexer Section group ctxsys.HTML_SECTION_GROUP' ); SELECT token_text FROM dr$datastore_text$i; 关于建立以及同步索引的时候发生的错误信息可以从 ctx_user_index_errors 用户视图 中查看。 9. 常见错误 下面就一些常见的错误信息给出解释和解决办法: 1.sync 失败 DRG-10595: ALTER INDEX T_DOC6_CT 失败 DRG-50857: Oracle error in drsxsopen ORA-01480: STR 赋值变量缺少空后缀 解决:这是 8i 的一个 bug, 但可以避免它,方法是在同步之前先发一个语句: ALTER SESSION SET nls_language=american; 2.create index 失败 ORA-29855: 执行 ODCIINDEXCREATE 例行程序时出错 ORA-20000: interMedia Text 错误: ORA-06512: 在"CTXSYS.DRUE", line 126 ORA-06512: 在"CTXSYS.TEXTINDEXMETHODS", line 54 ORA-06512: 在 line 1 解决:这是 8.1.6.3 之前的版本的一个 bug, 在处理中文时, 某个特殊字符造成的。 Oracle 向 索取补丁,或者自己去 metalink.Oracle.com 下载(需要 CSI 号码)。 3.create index 失败 RA-29855: 执行 ODCIINDEXCREATE 例行程序时出错 ORA-20000: interMedia Text 错误: DRG-50704: Net8 监听器没有运行或无法启动外部过程 ORA-28575: 无法打开与外部过程代理程序的 RPC 连接 ORA-06512: 在"CTXSYS.DRUE", line 126 Home: http://www.itpub.net Mail: epub@itpub.net
  41. 41. ITPub 电子杂志(总第四期) 第 41 页 ORA-06512: 在"CTXSYS.TEXTINDEXMETHODS", line 54 ORA-06512: 在 line 1 解决:明显的 extproc 配置不当。仔细阅读本文基本设置的第二步。 4.访问建有索引的表时失败 ora-29861: 域索引标记为 loading/failed/unusable 解决:这是该表的一个 intermedia 索引有问题,该索引要么没有正确建立,要么是某次同 步失败导致它状态异常。先查到是哪个索引: SELECT idx_name, idx_status FROM ctxsys.ctx_indexes; 然后同步该索引或者强制删除它: 重建:ALTER INDEX myindex REBUILD ONLINE PARAMETERS('sync'); 删除:DROP INDEX myindex FORCE; 5.使用 chinese_lexer 失败 ERROR at row 1: ORA-29855: err on ODCIINDEXCREATE ORA-20000: interMedia Text err: DRG-10502: index 1386 is not existing. DRG-11102: the lexer cann't analyze as SIMPLIFIED CHINESE_CHINA.ZHS16GBK ORA-06512: 在"CTXSYS.DRUE", line 126 ORA-06512: 在"CTXSYS.TEXTINDEXMETHODS", line 54 ORA-06512: 在 line 1 解决:chinese_lexer 只支持 utf8 字符集。现在你面临抉择:忍受 chinese vgram lexer 的 愚蠢,或者将数据库字符集改到 utf8, 但面对可能引起你的应用不能正确处理中文的风险 (先咨询 Oracle support, 并且与你的应用软件提供商联系)。 6.升级或应用 patch 后失败 ORA-29856: err when execute ODCIINDEXDROP ORA-20000: interMedia Texterr ORA-06508: PL/SQL: can not find program unit beingcalled ORA-06512: at "CTXSYS.DRUE", line 126 ORA-06512: at"CTXSYS.TEXTINDEXMETHODS", line 229 ORA-06512: at line 1 Home: http://www.itpub.net Mail: epub@itpub.net
  42. 42. ITPub 电子杂志(总第四期) 第 42 页 解决:这是 intermedia 的某个 object 没有正确产生或者编译。用 ctxsys 用户登录后,运行: $Oracle_home/ctx/admin/dr0pkh.sql 和 $Oracle_home/ctx/admin/dr0plb.sql 以重新产生所有的 package.你也可以直接察看 dba_objects 视图,找出那些属于 ctxsys 用户并且 status 为 invalid 的东西,重新产生或者 重新编译。(你可能会发现有许多这种东西,不要惊讶,Oracle 不会因此而崩溃)。 7.create index 失败 ERROR 位于第 1 行: ORA-29855: 执行 ODCIINDEXCREATE 例行程序时出错 ORA-20000: interMedia Text 错误: DRG-50857: Oracle error in driddl.IndexResume ORA-04030: 在尝试分配 524288 字节 (cursor work he,QERHJ Bit vector)时进程内存不足 ORA-06512: 在"CTXSYS.DRUE", line 126 ORA-06512: 在"CTXSYS.TEXTINDEXMETHODS", line 214 ORA-06512: 在 line 1 解决:引起这个问题可以有多种原因,首先你可以将 sort_area_size 这个参数减小到不多于 2M,这可以防止 Oracle 在创建索引时分配太多的 sort 内存而耗尽资源。但如果这不起作用, 而且你是 8.1.7, 则恭喜,你 hit 了 bug 1391737. 该 bug 在你要建索引的字段,如果某条 记录的长度超过 2000 字符时引起 Oracle 耗尽内存资源。别无它法,除了打 8.1.7.1B 的补 丁。 10.附录 10.1 ORACLE TEXT 资源: Oracle Text Application Developer's Guide Release 9.2 Oracle Text Reference Release 9.2 Oracle Text (formerly interMedia Text) Oracle Technology Network (OTN) discuss forum 10.2 关于索引性能的 FAQ This section answers some of the frequently asked questions about indexing performance. How long should indexing take? Answer: Indexing text is a resource-intensive process. Obviously, the speed of indexing will depend on the power of the hardware involved. Home: http://www.itpub.net Mail: epub@itpub.net
  43. 43. ITPub 电子杂志(总第四期) 第 43 页 As a benchmark, with an average document size of 5K, Oracle Text can index approximately 200 documents per second with the following hardware and parallel configuration: • 4x400Mhz Sun Sparc CPUs • 4 gig of RAM • EMC symmetrix (24 disks striped) • Parallel degree of 5 with 5 partitions • Index memory of 600MB per index process • XML news documents that averaged 5K in size • USER_DATASTORE Other factors such as your document format, location of your data, and the calls to user-defined datastores, filters, and lexers can have an impact on your indexing speed. Which index memory settings should I use? Answer: You can set your index memory with the system parameters DEFAULT_INDEX_MEMORY and MAX_INDEX_MEMORY. You can also set your index memory at run time with the CREATE INDEX memory parameter in the parameter string. You should aim to set the DEFAULT_INDEX_MEMORY value as high as possible, without causing paging. You can also improve Indexing performance by increasing the SORT_AREA_SIZE system parameter. Experience has shown that using a large index memory setting, even into hundreds of megabytes, will improve the speed of indexing and reduce the fragmentation of the final indexes. However, if set too high, then the memory paging that occurs will cripple indexing speed. With parallel indexing, each stream requires its own index memory. When dealing with very large tables, you can tune your database system global area (SGA) differently for indexing and retrieval. For querying, you are hoping to get as much information cached in the system global area's (SGA) block buffer cache as possible. So you should be allocating a large amount of memory to the block buffer cache. But this will not make any difference to indexing, so you would be better off reducing the size of the SGA to make more room for a large index memory settings during indexing. You set the size of SGA in your Oracle initialization file. See Also: Home: http://www.itpub.net Mail: epub@itpub.net
  44. 44. ITPub 电子杂志(总第四期) 第 44 页 Oracle Text Reference to learn more about Oracle Text system parameters. Oracle9i Database Administrator's Guide for more information on setting SGA related parameters. Oracle9i Database Performance Guide and Reference for more information on memory allocation and setting the SORT_AREA_SIZE parameter. How much disk overhead will indexing require? Answer: The overhead, the amount of space needed for the index tables, varies between about 50% of the original text volume and 200%. Generally, the larger the total amount of text, the smaller the overhead, but many small records will use more overhead than fewer large records. Also, clean data (such as published text) will require less overhead than dirty data such as emails or discussion notes, since the dirty data is likely to include many unique words from mis-spellings and abbreviations. A text-only index is smaller than a combined text and theme index. A prefix and substring index makes the index significantly larger. How does the format of my data affect indexing? Answer: You can expect much lower storage overhead for formatted documents such as Microsoft Word files since such documents tend to be very large compared to the actual text held in them. So 1GB of Word documents might only require 50MB of index space, whereas 1GB of plain text might require 500MB, since there is ten times as much plain text in the latter set. Indexing time is less clear-cut. Although the reduction in the amount of text to be indexed will have an obvious effect, you must balance this out against the cost of filtering the documents with the INSO filter or other user-defined filters. Can I index in parallel? Answer: Yes, you can index in parallel. Parallel indexing can improve index performance when you have a large amount of data, and have multiple CPUs. You use the PARALLEL keyword when creating the index: CREATE INDEX index_name ON table_name (column_name) INDEXTYPE IS ctxsys.context PARAMETERS ('...') PARALLEL 3; Home: http://www.itpub.net Mail: epub@itpub.net
  45. 45. ITPub 电子杂志(总第四期) 第 45 页 This will create the index with up to three separate indexing processes depending on your resources. Note: It is no longer necessary to create a partitioned table to index in parallel as was the case in earlier releases. Note: When you create a local index in parallel as such (which is actually run in serial), subsequent queries are processed in parallel by default. Creating a non-partitioned index in parallel does not turn on parallel query processing. Parallel querying degrades query throughput especially on heavily loaded systems. Because of this, Oracle recommends that you disable parallel querying after indexing. To do so, use ALTER INDEX NOPARALLEL. How do I create a local partitioned index in parallel? Answer: You can improve indexing performance by creating a local index in parallel. However, currently you cannot create a local partitioned index in parallel using the PARALLEL parameter with CREATE INDEX. In such cases the parameter is ignored and indexing proceeds serially. To create a local index in parallel, create an unusable index first, then run the DBMS_PCLXUTIL.BUILD_PART_INDEX utility. In this example, the base table has three partitions. We create a local partitioned unusable index first, the run the DBMS_PCLUTIL.BUILD_PART_INDEX, which builds the 3 partitions in parallel (inter-partition parallelism). Also inside each partition, index creation is done in parallel (intra-partition parallelism) with a parallel degree of 2. CREATE INDEX tdrbip02bx ON tdrbip02b(text) indextype is ctxsys.context local (partition tdrbip02bx1, partition tdrbip02bx2, partition tdrbip02bx3) Home: http://www.itpub.net Mail: epub@itpub.net
  46. 46. ITPub 电子杂志(总第四期) 第 46 页 unusable; exec dbms_pclxutil.build_part_index(3,2,'TDRBIP02B','TDRBIP02BX',TRUE); How can I tell how far my indexing has got? Answer: You can use the CTX_OUTPUT.START_LOG procedure to log output from the indexing process. Filename will normally be written to $ORACLE_HOME/ctx/log, but you can change the directory using the LOG_DIRECTORY parameter in CTX_ADM.SET_PARAMETER. See Also: Oracle Text Reference to learn more about using this procedure. 8.3Frequently Asked Questions About Updating the Index This section answers some of the frequently asked questions about updating your index and related performance issues. How often should I index new or updated records? Answer: How often do you need to? The less often you run reindexing with CTX_DLL.SYNC_INDEX then the less fragmented your indexes will be, and the less you will need to optimize them. However, this means that your data will become progressively more out of date, which may be unacceptable for your users. Many systems are OK with overnight indexing. This means data that is less than a day old is not searchable. Other systems use hourly, ten minute, or five minute updates. See Also: Oracle Text Reference to learn more about using CTX_DDL.SYNC_INDEX. "Managing DML Operations for a CONTEXT Index" in Chapter 2, "Indexing" How can I tell when my indexes are getting fragmented? Home: http://www.itpub.net Mail: epub@itpub.net
  47. 47. ITPub 电子杂志(总第四期) 第 47 页 Answer: The best way is to time some queries, run index optimization, then time the same queries (restarting the database to clear the SGA each time, of course). If the queries speed up significantly, then optimization was worthwhile. If they don't, you can wait longer next time. You can also use CTX_REPORT.INDEX_STATS to analyze index fragmentation. See Also: Oracle Text Reference to learn more about using the CTX_REPORT package. "Index Optimization" in Chapter 2, "Indexing". Does memory allocation affect index synchronization? Answer: Yes, the same way as for normal indexing. But of course, there are often far fewer records to be indexed during a synchronize operation, so it is not usually necessary to provide hundreds of megabytes of indexing memory 10.4 示例 JSP 代码 This section describes the JSP web application. Web Application Prerequisites This application has the following requirements: • Your Oracle database (version 8.1.6 or higher) is up and running. • You have a web server such as Apache up and running and correctly configured to send requests to the Oracle9i server. JSP Sample Code: search_html.jsp <%@ page import="java.sql.* , Oracle.jsp.dbutil.*" %> <jsp:useBean id="name" class="Oracle.jsp.jml.JmlString" scope="request" > <jsp:setProperty name="name" property="value" param="query" /> </jsp:useBean> <% Home: http://www.itpub.net Mail: epub@itpub.net
  48. 48. ITPub 电子杂志(总第四期) 第 48 页 String connStr="jdbc:Oracle:thin:@localhost:1521:betadev"; java.util.Properties info = new java.util.Properties(); Connection conn = null; ResultSet rset = null; Statement stmt = null; if (name.isEmpty()) { %> <html> <title>search1 Search</title> <body> <center> <form method=post> Search for: <input type=text name=query size=30> <input type=submit value="Search"> </form> </center> <hr> </body> </html> <% } else { %> <html> <title>Search</title> <body> <center> <form method=post action="search_html.jsp"> Search for: <input type=text name="query" value=<%= name.getValue() %> size=30> <input type=submit value="Search"> </form> </center> <% try { Home: http://www.itpub.net Mail: epub@itpub.net
  49. 49. ITPub 电子杂志(总第四期) 第 49 页 DriverManager.registerDriver(new Oracle.jdbc.driver.OracleDriver() ); info.put ("user", "ctxdemo"); info.put ("password","ctxdemo"); conn = DriverManager.getConnection(connStr,info); stmt = conn.createStatement(); String theQuery = request.getParameter("query"); String myQuery = "select /*+ FIRST_ROWS */ rowid, tk, title, score(1) scr from search_table where contains(text, '"+theQuery+"',1 ) > 0 order by score(1) desc"; rset = stmt.executeQuery(myQuery); String color = "ffffff"; int myTk = 0; String myTitle = null; int myScore = 0; int items = 0; while (rset.next()) { myTk = (int)rset.getInt(2); myTitle = (String)rset.getString(3); myScore = (int)rset.getInt(4); items++; if (items == 1) { %> <center> <table border="0"> <tr bgcolor="#6699CC"> <th>Score</th> <th>Title</th> </tr> <% } %> <tr bgcolor="#<%= color %>"> <td> <%= myScore %>%</td> <td> <%= myTitle %> </td> </tr> <% if (color.compareTo("ffffff") == 0) color = "eeeeee"; Home: http://www.itpub.net Mail: epub@itpub.net
  50. 50. ITPub 电子杂志(总第四期) 第 50 页 else color = "ffffff"; } } catch (SQLException e) { %> <b>Error: </b> <%= e %><p> <% } finally { if (conn != null) conn.close(); if (stmt != null) stmt.close(); if (rset != null) rset.close(); } %> </table> </center> </body></html> <% } (END) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Home: http://www.itpub.net Mail: epub@itpub.net
  51. 51. ITPub 电子杂志(总第四期) 第 51 页 9i 新特点:SPFILE 的使用 作者:盖国强 (ITPUB:Eygle) 在 Oracle9i 中,一个新的文件被引入-spfile,spfile 用于服务器端,管理初始化参数。 在 9i 以前,Oracle 使用 pfile 存储初始化参数设置,这些参数在实例启动时被读取,任何修改 需要重起实例才能生效;使用 spfile 你可以使用 ALTER SYSTEM 或者 ALTER SESSION 来动 态修改那些可动态修改的参数,所有更改可以立即生效,你可以选择使更改只应用于当前实例还 是同时应用到 spfile。这就使得所有对 spfile 的修改都可以在命令行完成,我们可以彻底告别手 工修改初始化参数文件,这就大大减少了人为错误的发生。 SPFILE 是一个二进制文件,可以使用 RMAN 进行备份,这样实际上 Oracle 把参数文件也纳入 了备份恢复管理。 除了第一次启动数据库需要 PFILE(然后可以根据 PFILE 创建 SPFILE),我们可以不再需要 PFILE,ORACLE 强烈推荐使用 spfile,应用其新特性来存储和维护初始化参数设置。 一. 创建 SPFILE 缺省的,ORACLE 使用 PFILE 启动数据库,SPFILE 必须由 PFILE 创建,新创建的 SPFILE 在 下一次启动数据库时生效,CREATE SPFILE 需要 SYSDBA 或者 SYSOPER 的权限: 语法如下: CREATE SPFILE[=’SPFILE-NAME’] FROM PFILE[=’PFILE-NAME’] 例: SQL> create spfile from pfile; 缺省的,spfile 创建到系统缺省目录 (Unix: $ORACLE_HOME/dbs; NT: $ORACLE_HOMEdatabase) 如果 SPFILE 已经存在,那么创建会返回以下错误: SQL> create spfile from pfile; create spfile from pfile Home: http://www.itpub.net Mail: epub@itpub.net
  52. 52. ITPub 电子杂志(总第四期) 第 52 页 * ERROR 位于第 1 行: ORA-32002: 无法创建已由例程使用的 SPFILE 这也可以用来判断当前是否使用了 SPFILE 文件。 然而意外的时,Oracle 并没有向其他文件一样,在运行期间保持锁定,让我们作以下试验: SQL> host rename SPFILEEYGLEN.ORA SPFILEEYGLEN.ORA.BAK SQL> alter system set db_cache_size=24M scope=both; 系统已更改。 SQL> host dir *.ora 驱动器 E 中的卷是 Doc 卷的序列号是 980C-8EFF E:OracleOra9iR2database 的目录 2003-02-10 14:35 2,048 PWDeyglen.ORA 1 个文件 2,048 字节 0 个目录 150,347,776 可用字节 SQL> alter system set db_cache_size=24M scope=spfile; alter system set db_cache_size=24M scope=spfile * ERROR 位于第 1 行: ORA-27041: 无法打开文件 OSD-04002: 无法打开文件 O/S-Error: (OS 2) 系统找不到指定的文件。 SQL> host rename SPFILEEYGLEN.ORA.BAK SPFILEEYGLEN.ORA SQL> alter system set db_cache_size=24M scope=spfile; 系统已更改。 SQL> 估计 Oracle 以后会想办法来锁定这个文件。 Home: http://www.itpub.net Mail: epub@itpub.net
  53. 53. ITPub 电子杂志(总第四期) 第 53 页 二. 使用 SPFILE 重新启动数据库,使用 startup 命令,Oralce 将会按照以下顺序在缺省目录中搜索参数文 件: a. spfile${ORACLE_SID}.ora 缺省目录 UNIX: ${ORACLE_HOME}/dbs/ NT: ${ORACLE_HOME}database b. spfile.ora 缺省目录 UNIX: ${ORACLE_HOME}/dbs/ NT: ${ORACLE_HOME}database c. init${ORACLESID}.ora 缺省目录 UNIX: ${ORACLE_HOME}/dbs/ NT: ${ORACLE_HOME}database or ${ORACLE_HOME}admindb_namepfile 创建了 spfile,重新启动数据库,Oracle 会按顺序搜索以上目录,spfile 就会自动生效。 Home: http://www.itpub.net Mail: epub@itpub.net
  54. 54. ITPub 电子杂志(总第四期) 第 54 页 三. 使用 pfile/spfile 启动数据库 如果你想使用 pfile 启动数据库,你可以在启动时指定 pfile 或者删除 spfile. SQL> startup pfile='E:Oracleadmineyglenpfileinit.ora'; 你不能以同样的方式指定 spfile,但是可以创建一个包含 spfile 参数的 pfile 文件,指向 spfile. SPFILE 是一个自 Oracle9i 引入的初始化参数,类似于 IFILE 参数。 SPFILE 参数用于定义非 缺省路径的 spfile 文件。 你可以在 PFILE 链接到 SPFILE 文件,同时在 PFILE 中定义其他参数,如果参数重复设置,后 读取的参数将取代先前的设置。 PFILE 参数的使用,例如: 这是我们使用 SPFILE 启动的情况, SQL> startup ORACLE 例程已经启动。 Total System Global Area 135338868 bytes Fixed Size 453492 bytes Variable Size 109051904 bytes Database Buffers 25165824 bytes Redo Buffers 667648 bytes 数据库装载完毕。 数据库已经打开。 SQL> SHOW parameter log_archive_start NAME TYPE VALUE ------------------------------------ ------------ -------- log_archive_start boolean TRUE SQL> SHOW parameter spfile NAME TYPE VALUE -------------------- --------- ------------------------------- spfile string %ORACLE_HOME%DATABASESPFILE%ORACLE_SID%.ORA Home: http://www.itpub.net Mail: epub@itpub.net
  55. 55. ITPub 电子杂志(总第四期) 第 55 页 SQL> 我们修改 PFILE 文件内容如下: #Pfile link to SPFILE SPFILE= 'E:OracleOra9iR2databaseSPFILEEYGLEN.ORA' log_archive_start = false 可以预见这个 log_archive_start 参数设置将会代替 SPFILE 中的设置: SQL> startup pfile='e:initeyglen.ora' ORACLE 例程已经启动。 Total System Global Area 135338868 bytes Fixed Size 453492 bytes Variable Size 109051904 bytes Database Buffers 25165824 bytes Redo Buffers 667648 bytes 数据库装载完毕。 数据库已经打开。 SQL> show parameter spfile NAME TYPE VALUE ---------------- ------- --------- ---------------------- spfile string E:OracleOra9iR2databaseSPFLEEYGLEN.ORA SQL> SHOW parameter log_archive_start NAME TYPE VALUE ------------------------------------ -------- ----------- log_archive_start boolean FALSE 然后我们可以使用 ALTER SYSTEM 方式将修改固定到 SPFILE. SQL> ALTER SYSTEM SET log_archive_start=FALSE SCOPE=spfile; Home: http://www.itpub.net Mail: epub@itpub.net
  56. 56. ITPub 电子杂志(总第四期) 第 56 页 系统已更改。 所以你也可以通过如上方式在启动时修改初始化参数。比我们在本文最后介绍的导入导出方 法要简便的多。 Home: http://www.itpub.net Mail: epub@itpub.net
  57. 57. ITPub 电子杂志(总第四期) 第 57 页 四. 修改参数 可以通过 ALTER SYSTEM 或者导入导出来更改 SPFILE 的内容。 ALTER SYSTEM 增加了一个新选项:SCOPE。SCOPE 参数有三个可选值:MEMORY 、 SPFILE 、BOTH。 MEMORY:只改变当前实例运行 SPFILE:只改变 SPFILE 的设置 BOTH:改变实例及 SPFILE 1. SCOPE=MEMORY SQL> SHOW parameter timed_statistics NAME TYPE VALUE ------------------------------------ ------ -------------- timed_statistics boolean TRUE SQL> ALTER SYSTEM SET timed_statistics=FALSE SCOPE=MEMORY; 系统已更改。 SQL> SHOW parameter timed_statistics NAME TYPE VALUE ------------------------------------ ------ -------------- timed_statistics boolean FALSE SQL> SHUTDOWN immediate 数据库已经关闭。 已经卸载数据库。 ORACLE 例程已经关闭。 SQL> startup ORACLE 例程已经启动。 Total System Global Area 135338868 bytes Fixed Size 453492 bytes Variable Size 109051904 bytes Database Buffers 25165824 bytes Redo Buffers 667648 bytes 数据库装载完毕。 数据库已经打开。 Home: http://www.itpub.net Mail: epub@itpub.net
  58. 58. ITPub 电子杂志(总第四期) 第 58 页 SQL> show parameter timed_statistics NAME TYPE VALUE ------------------------------------ ------- ------------ timed_statistics boolean TRUE 2. SCOPE=SPFILE SQL> show parameter timed_statistics NAME TYPE VALUE ------------------------------------ ------- ------------ timed_statistics boolean TRUE SQL> ALTER SYSTEM SET timed_statistics=FALSE SCOPE=SPFILE; 系统已更改。 SQL> show parameter timed_statistics NAME TYPE VALUE ------------------------------------ ------- ------------ timed_statistics boolean TRUE SQL> SHUTDOWN immediate 数据库已经关闭。 已经卸载数据库。 ORACLE 例程已经关闭。 SQL> STARTUP ORACLE 例程已经启动。 Total System Global Area 135338868 bytes Fixed Size 453492 bytes Variable Size 109051904 bytes Database Buffers 25165824 bytes Redo Buffers 667648 bytes 数据库装载完毕。 数据库已经打开。 SQL> SHOW parameter timed_statistics NAME TYPE VALUE ------------------------------------ ------- ------------ Home: http://www.itpub.net Mail: epub@itpub.net
  59. 59. ITPub 电子杂志(总第四期) 第 59 页 timed_statistics boolean FALSE SQL> 3. SCOPE = BOTH 使用 BOTH 选项实际上等同于不带参数的 ALTER SYSTEM 语句。 注意:如果修改静态参数,那么需要指定 SPFILE 参数,否则将会报错。 SQL> SHOW parameter timed_statistics NAME TYPE VALUE ----------------------------------- -------- ----------- timed_statistics boolean FALSE SQL> ALTER SYSTEM SET timed_statistics=TRUE SCOPE=BOTH; 系统已更改。 SQL> SHOW parameter timed_statistics NAME TYPE VALUE ------------------------------------ -------- ---------- timed_statistics boolean TRUE SQL> SHUTDOWN immediate 数据库已经关闭。 已经卸载数据库。 ORACLE 例程已经关闭。 SQL>STARTUP ORACLE 例程已经启动。 Total System Global Area 135338868 bytes Fixed Size 453492 bytes Variable Size 109051904 bytes Database Buffers 25165824 bytes Redo Buffers 667648 bytes 数据库装载完毕。 数据库已经打开。 Home: http://www.itpub.net Mail: epub@itpub.net
  60. 60. ITPub 电子杂志(总第四期) 第 60 页 SQL> SHOW parameter timed_statistics NAME TYPE ALUE ------------------------------------ -------- ---------- timed_statistics boolean TRUE SQL> ALTER SYSTEM SET sql_trace=FALSE SCOPE=BOTH; ALTER SYSTEM SET sql_trace=FALSE SCOPE=BOTH * ERROR 位于第 1 行: ORA-02095: 无法修改指定的初始化参数 SQL> ALTER SYSTEM SET sql_trace=FALSE SCOPE=SPFILE; 系统已更改。 4.你也可以在数据库 shutdown 时创建和修改 spfile,例如: SQL> show sga Total System Global Area 135338868 bytes Fixed Size 453492 bytes Variable Size 109051904 bytes Database Buffers 25165824 bytes Redo Buffers 667648 bytes SQL> SHUTDOWN immediate 数据库已经关闭。 已经卸载数据库。 ORACLE 例程已经关闭。 SQL> create pfile from spfile; 文件已创建。 SQL> create spfile from pfile; 文件已创建。 SQL> Home: http://www.itpub.net Mail: epub@itpub.net

×