首页 Oracle9i中全文检索的创建与使用-免费阅读

Oracle9i中全文检索的创建与使用-免费阅读

举报
开通vip

Oracle9i中全文检索的创建与使用-免费阅读Oracle9i中全文检索的创建与使用-免费阅读 Oracle9i中全文检索的创建与使用前言 搜索文本 设置 建立索引 索引简介 索引类型和限制 权限和临时表空间 CONTEXT 索引 CONTEXT 索引的结构 建立索引 索引参数 DATASTORE FILTER SECTION STORAGE LEXER STOP LISTS WORD LISTS OTHERS 1 索引维护 查看索引错误 删除索引 重建索引 删除参数 管理DML 同步 优化 检索 C...

Oracle9i中全文检索的创建与使用-免费阅读
Oracle9i中全文检索的创建与使用-免费阅读 Oracle9i中全文检索的创建与使用前言 搜索文本 设置 建立索引 索引简介 索引类型和限制 权限和临时表空间 CONTEXT 索引 CONTEXT 索引的结构 建立索引 索引参数 DATASTORE FILTER SECTION STORAGE LEXER STOP LISTS WORD LISTS OTHERS 1 索引维护 查看索引错误 删除索引 重建索引 删除参数 管理DML 同步 优化 检索 CONTAINS Logical Operator 优化查询 分区 常见错误 附录 ORACLE TEXT资源 Frequently Asked Questions About Indexing Performance Frequently Asked Questions About Updating the Index JSP范例 1前言 Oracle从7.3开始支持全文检索,即用户可以使用Oracle服务器的上下文(ConText)选项完成基于文本的查询。具体可以采用通配符查找、模糊匹配、相关分类、近似查找、条件加权和词意扩充等方法。在Oracle8.0.x中称为ConText,在Oracle8i中称为interMedia Text.在 Oracle9i中称为Oracle Text. 本篇主要介绍Oracle Text的基本结构和简单应用。 Oracle Text是9I 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 版和企业版的一部分。Oracle9i将全文检索功能做为内置功能提供给用户,使得用户在创建数据库实例时自动安装全文检索。 Oracle Text的应用领域有很多: , 搜索文本 :需要快捷有效搜索文本数据的应用程序 , 管理多种文档:允许搜索各种混和文档格式的应用程序,包括 ord,excel,lotus等 , 从多种数据源中检索文本:不仅来自oracle数据库中的文本数据,而且可以 来自Internet和文件系统的文本数据 , 搜索XML应用程序 1.1搜索文本 2 不使用oracle text功能,也有很多方法可以在oracle数据库中搜索文本.可以使用标准的INSTR函数和LIKE操作符实现. select * from mytext where instr(thetext,'Oracle')>0; select * from mytext where thetext like '%Oracle%'; 有很多时候 使用instr和like是很理想的, 特别是搜索仅跨越很小的表的时候.然而通过这些文本定位的方法将导致全表扫描,对资源来说消耗比较昂贵,而且实现的搜索功能也非常有限. 利用Oracle Text,你可以回答如“在存在单词‘Oracle’的行同时存在单词’Corporation’而且两单词间距不超过10个单词的文本‘,‘查询含有单词’Oracle’或者单词’ california’的文本,并且将结果按准确度进行排序‘,’含有词根train的文本‘。以下的sql代码实现了如上功能。我们且不管这些语法是如何使用的。 drop 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 3 LSNRCTL for Solaris: Version 8.1.5.0.0 - Production on 31-MAR-99 18:57:49 (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 ( quick_id, text ) 4 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 If everything is OK, you will get: Index created. Now try some queries: 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 2建立索引 2(1索引简介 5 利用Oracle Text对文档集合进行检索的时候,你必须先在你的文本列上建立索引。索引将文本打碎分成很多记号(token),这些记号通常是用空格分开的一个个单词。 Oracle Text应用的实现实际上就是一个 数据装载—> 索引数据—>执行检索 的一个过程。 2(1(1索引类型和限制 建立的Oracle Text索引被称为域索引(domain index),包括4种索引类型: CONTEXT, CTXCAT, CTXRULE or CTXXPATH. 依据你的应用程序和文本数据类型你可以任意选择一种。可以利用Create Index建立这4种索引。下面说一下这4种索引的使用环境。 查询操作索引类型 描述 符 CONTEXT 用于对含有大量连续文本数据进行检索。支持CONTAINS word,html,xml,text等很多数据格式。支持中文字符集, 支持分区索引,唯一支持并行创建索引(Parallel indexing)的索引类型。 对表进行DML操作后,并不会自动同步索引。需要手工 同步索引 CTXCAT 当使用混合查询语句的时候可以带来很好的效率。适合CATSEARCH 于查询较小的具有一定结构的文本段。具有事务性,当 更新主表的时候自动同步索引。 The CTXCAT index does not support table and index 6 查询操作索引类型 描述 符 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. MATCHES You 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 索引 2.2.1 CONTEXT 索引的结构 7 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; 8 名称 是否为空 类型 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 可以看到,该表中保存的其实就是Oracle 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 你的文档后,生成的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)。根据不同的参数构建索引,可以应用于很多实际环境。 Class Description Datastore 从哪里得到数据, Filter 将数据转换成文本 Lexer 正在索引什么语言, Wordlist 应该如何展开茎干和模糊查询 Storage 如何存储索引 Stop List 什么单词或者主题不被索引, 9 Class Description Section Group 允许在区段内查询吗,如何定义文档区段。这把文档转换成普 通文本 这些参数在建立CONTEXT索引过程中将按下图顺序对索引进程起作用。在本篇 中提供一些简单demo会看到各个参数的作用. 10 Default CONTEXT Index Example 建立索引时,系统默认文档存储在数据库的文本列中。如果不显示的指定索引参数,系统会自动探测文本语言,数据类型和文档格式。 CREATE INDEX myindex ON docs(text) INDEXTYPE IS CTXSYS.CONTEXT; 如上命令建立了一个默认参数的CONTEXT索引myindex.系统默认: 1. 文本存储在数据库中。可以是CLOB, BLOB, BFILE, VARCHAR2, or CHAR类型的文本数据。 2. 文本列语言是数据库建立时的默认的字符集。 3. 使用数据库默认的终止目录stoplist.stoplist记录存在于文本列 中但不对其索引的词。 4. 允许模糊查询。 2.3索引参数 2.3.1DataStore 11 指明你的文本是如何存储的。系统默认文档储存在数据库内的文本列(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. 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. 12 Datastore Type Use When 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'); create index mc_idx on mc(name) indextype is ctxsys.context parameters('datastore mymds') / select *from mc where contains(name,'biti')>0 ; 问:如何实现对主/从表的全文检索, 答:使用类Detail_DataStore。这个类经过设计,供主/从表格使用,其中大量文本存储在从表表格列中。在进行索引之前把多个从表行联接为一个文档,使用外来关键码识别行,外键关系必须已逻辑的方式存在,但不必作为数据库约束条 13 件。注意在不更改主表的情况下更改从表,不会更新索引。解决这个的办法是更新主列的值,触发索引的重新构建,或者手工设置和重新构建索引。否则,应该存在未使用的列,来保持SQL语法的完整性。如下面例子中的purchase_order 表的line_item_body列。 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 ) 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 14 parameters( 'datastore po_pref' ) / select id from purchase_order where contains( line_item_body, 'Oracle' ) > 0 / 2.3.2Filter 过滤 一旦汇编了文档,它就沿管道传递。接下来这个阶段是过滤(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区分组 区分组(Section Groups)是与interMedia一起使用XML的关键。这些组处理XML(或者HTML)文档,输出两个数据流,即区段界限和文本内容。默认是NULL_SECTION_GROUP,它简单的直接传递文本,不执行任何修改和处理。HTML_SECTION_GROUP是专门用来处理HTML文档的。 下面的例子中显示如何处理HTML文档。 set echo on drop table my_html_docs; create table my_html_docs ( id number primary key, html_text varchar2(4000)) 15 / insert into my_html_docs( id, html_text ) values( 1,'Oracle TechnologyThis is about the wonderful marvels of 8i and 9i' ) /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 / --也可以检索到 区段界限内的文本。但由于HTML文件中的一些标记如 等对我们没有提供有用的信息。而且在索引中还浪费了空间和CPU。因此HTML标记不应该被索引 --我们可以定制我们自己的区段标记。 可以查询在某个区段出现的单词 begin ctx_ddl.create_section_group('my_section_group','BASIC_SECTION_GROUP'); ctx_ddl.add_field_section( group_name => 'my_section_group', 16 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; 下面是如何检索XML文档的例子 InterMedia Text 支持索引XML文档通过指定区段组。区段组就是XML文档中预先定义的节点.你可以用WithIn在指定检索某个节点,提高了检索的准确性。 1) Firstly, create the table to store our XML documents create table employee_xml( id number primary key, xmldoc clob ) / 2) Insert a sample document (the DTD is not required) insert into employee_xml values( 1, ' 17 ]> Joel Kallman Oracle Service Industries Technology Group Technologist '); 3) Create our interMedia Text section group called 'xmlgroup', Add the tags Name and Dept to the 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) Now, execute a query, searching for a name within a specific section select id from employee_xml where contains(xmldoc, 'Joel within Name') > 0; 18 6) Only non-empty tags will be indexed, but not the tag names themselves. Thus, the following queries will return zero rows. 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 19 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) And once again, we should be able to locate our document using a section search select id from employee_xml where contains(xmldoc, 'Technologist within Title') > 0; 2(3(3Storage 类 Storage(存储空间)组的类只含有BASIC_STORAGE.默认情况下,BASIC_STORAGE对象的属性是空的。我们通常需要定制自己的STORAGE类,来控制索引的存储参数以及存储空间。建立全文索引的时候我们通常会考虑表段dr$indexname$I,,dr$indexname$R,索引段dr$indexname$X的空间分配。 type Description BASIC_STORAGE 为CONTEXT索引指定默认的存储参数 BASIC_STORAGE 有如下参数 Attribute Attribute Value 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. 20 Attribute Attribute Value 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 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 Example 21 下面我们自己定制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.contex t parameters('storage mystore'); / ---查看段的存储参数,这样方便了以后数据容量的扩展。 select segment_name,tablespace_name from user_segments where segment_name like ’%HTML1%’; 2.3.4设置词法分析器(lexer) 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: ‘中’,‘中国’,‘国人’, 22 ‘人民’,‘民站’,‘站起’,起来’,‘来了’,‘了’。可以看出, 这种分析方法,实现算法很简单,并且能实现‘一网打尽’,但效率则是差 强人意。 , 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'); 这样建立的全文检索索引,就会使用chinese_vgram_lexer作为分析器。 相应的,索引中文就比索引英文占用的表空间多了许多。Oracle Text为了性能不得不牺牲了空间。如下是我的简单存储空间测试 文本数据量 索引数据量(4个表段和1个索引段) 6M 80M 80M 900M 230M 2880M 1344M 15232M 2.3.5STOP Lists类 Stop List只不过是被索引忽略的单词的列表。这些通常是常见的单词,正常情况下不会以任何方式查询它们,因此,索引它们纯粹是表格空间和处理器周期的浪费。在具体的应用中,可能存在这样的单词,它们在特定的文集中出现的频率太大,无法提供有意义的内容,特别是常用的单词。 Stop List可以含有最多4095个单词,每个单词最多64个字符,同时为英语和其它语言提供了默认列表。 下图是Chinese Stoplist (Simplified)的默认列表 23 你可以查看英文的默认列表 select spw_word from DR$STOPWORD; 你可以查询ctx_stoplists和ctx_stopwords 视图来观察这些语言。 SQL> execute ctx_ddl.create_stoplist('stoppref'); select *from ctx_stoplists; 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.5Lists类 要考虑的最后一个类是单一的Word List类,即BASIC_WORDLIST。创建索引时不使用这个类,这个类只在某些高级形式的查询中使用。茎干查询使用从Xerox公司许可的技术,来匹配单词与通用的语言根。 24 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索引维护 这节讲一下当索引操作失败的时候所要进行的一些处理。 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不能决定索引的状态,例如建立索引的时候发生错误,没有成功结束,则需要强制删除索引。 25 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 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表删除。 26 当基表中的被索引文档发生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; This statement gives output in the form: PND_INDEX_NAME PND_ROWID TIMESTAMP ------------------------------ ------------------ -------------------- MYINDEX AAADXnAABAAAS3SAAC 06-oct-1999 15:56:50 同步和优化方法: 可以使用Oracle提供的ctx_ddl包同步和优化索引。 对于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 rebuild parameters ('sync') 更新索引。 27 alter index search_idx rebuild parameters( 'sync' ) / Index altered. 9i提供了新的专门用于更新索引的包ctx_ddl.sync_index(…) 4.1.2CTX_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); 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; 28 其中score(1)为oracle为全文查询计算的主题符合程度。 4.2索引优化 经常的索引同步将会导致你的CONTEXT索引产生碎片。索引碎片严重的影响了查询的反应速度。你可以定期优化索引来减少碎片,减少索引大小,提高查询效率。为了更好的理解索引优化,我们先看看索引的结构以及碎片是如何产生的。 CONTEXT索引是反向索引,每一个索引项目都包括单词和这个单词所出现过的文档地址。例如在一个初始化索引过程中,单词DOG可以包括如下条目 DOG DOC1 DOC3 DOC5 当新的文档被包含到表的时候,索引被同步。如果新行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’); 29 end; 4.2.2 Single Token Optimization 除了优化整个索引以外,你还可以专门对某个标记(token)进行优化。你可以仅仅优化那些经常查询的标记(token),而不必花太多时间在很少查询的单词上。 例如,你可以专门优化token DOG,它经常被检索或者经常被更新。这样可以提高查询这个token的查询效率。 begin ctx_ddl.optimize_index('myidx','token', TOKEN=>'DOG'); end; 4.2.3FAST MODE 这种方法仅仅使碎片行紧凑。但是,旧的数据并不从索引中删除。 begin 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 30 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 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。 31 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; 返回了得分最高的前10条记录 5.2Logical Operators 允许你组合搜索条件,通过使用AND,OR等逻辑。 Operator Symbol Description Example Expression AND & Use the AND operator to 'cats AND dogs' search for documents 'cats & dogs' that contain at least one occurrence of each of the query terms. Score returned is the minimum of the operands. OR | Use the OR operator to 'cats | dogs' search for documents 'cats OR dogs' that contain at least one occurrence of any of the query terms. Score returned is the maximum of the operands. NOT ~ Use the NOT operator to To obtain the documents that search for documents contain the term animals but that contain one query not dogs, use the following 32 Operator Symbol Description Example Expression term and not another. expression: 'animals ~ dogs' ACCUM , Use the ACCUM operator The following query returns to search for documents all documents that contain that contain at least the terms dogs, cats and one occurrence of any of puppies giving the highest the query terms. The scores to the documents that accumulate operator contain all three terms: ranks documents 'dogs, cats, puppies' according to the total term weight of a document. EQUIV = Use the EQUIV operator The following example to specify an acceptable returns all documents that substitution for a word contain either the phrase in a query. or alsatians are big dogs German shepherds are big : dogs 'German 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 33 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分区 CONTEXT索引支持在分区表山建立本地分区索引,但仍然有一些限制。如下 , 分区表必须是按范围分区,不支持HASH分区和复合分区。 , 你应该为每个分区指定索引分区名称。如果不指定,系统默认为每 个分区表指定。分区索引列表的顺序必须和分区表的顺序一致。 , 可以为每个分区分别指定PRAMETERS参数,但是PARAMETERS只允许 包括STORAGE和MEMEROY参数。 , 不能指定ONLINE建立索引。 可以查询CTX_INDEX_PARTITIONS或者CTX_USER_INDEX_PARTITIONS获得 更多信息。 6.1Creating a Local Partitioned Index 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'); 34 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’)); 6.2Creating a Local Partitioned Index in Parallel 可以并行的建立分区索引,加快建立索引速度。但是建立索引不能“一步到位“。我们必须先建立一个unusable索引,然后利DBMS_PCLXUTIL.BUILD_PART_INDEX 并行建立索引。 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 / 6.3查询分区索引 你可以在单个表分区上进行全文检索。 35 select * from part_tab partition (p_tab4) where contains(b,'oracle') >0 ORDER BY SCORE; 7常见错误 下面就一些常见的错误信息给出解释和解决办法: 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 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; 36 然后同步该索引或者强制删除它: 重建: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 解决:这是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)时进程内存不足 37 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 的补丁。 8附录 8(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 8(2Frequently Asked Questions About Indexing Performance 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. 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. 38 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: 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? 39 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 -spellings and abbreviations.include many unique words from mis 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; This will create the index with up to three separate indexing processes depending on your resources. Note: 40 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, 41 partition tdrbip02bx2, partition tdrbip02bx3) 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 42 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? 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 8(4示例JSP代码 The JSP Web Application 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. 43 JSP Sample Code: search_html.jsp <%@ page import="java.sql.* , oracle.jsp.dbutil.*" %> <% 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()) { %> search1 Search
Search for:

<% } else { %> Search
44
Search for: size=30>
<% try { 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) { %>
45 <% } %> <% if (color.compareTo("ffffff") == 0) color = "eeeeee"; else color = "ffffff"; } } catch (SQLException e) { %> Error: <%= e %>

<% } finally { if (conn != null) conn.close(); if (stmt != null) stmt.close(); if (rset != null) rset.close(); } %>

Score Title
<%= myScore %>% <%= myTitle %>
<% } 46
本文档为【Oracle9i中全文检索的创建与使用-免费阅读】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
最新资料
资料动态
专题动态
is_531654
暂无简介~
格式:doc
大小:203KB
软件:Word
页数:60
分类:
上传时间:2018-03-08
浏览量:5