Oracle全文索引

简介: Oracle全文索引 一、设置词法分析器 Oracle实现全文检索,其机制其实很简单。即通过Oracle专利的词法分析器(lexer),将文章中所有的表意单元(Oracle 称为 term)找出来,记录在一组 以dr$开头的表中,同时记下该term出现的位置、次数、hash 值等信息。

Oracle全文索引




一、设置词法分析器

Oracle实现全文检索,其机制其实很简单。即通过Oracle专利的词法分析器(lexer),将文章中所有的表意单元(Oracle 称为 term)找出来,记录在一组 dr$开头的表中,同时记下该term出现的位置、次数、hash 值等信息。检索时,Oracle 从这组表中查找相应的term,并计算其出现频率,根据某个算法来计算每个文档的得分(score,即所谓的匹配率。而lexer则是该机制的核心,它决定了全文检索的效率。Oracle 针对不同的语言提供了不同的 lexer, 而我们通常能用到其中的三个:

 

n      basic_lexer: 针对英语。它能根据空格和标点来将英语单词从句子中分离,还能自动将一些出现频率过高已经失去检索意义的单词作为垃圾处理,如if , is 等,具有较高的处理效率。但该lexer应用于汉语则有很多问题,由于它只认空格和标点,而汉语的一句话中通常不会有空格,因此,它会把整句话作为一个term,事实上失去检索能力。以中国人民站起来了这句话为例,basic_lexer 分析的结果只有一个term ,就是中国人民站起来了。此时若检索中国,将检索不到内容。

n      chinese_vgram_lexer: 专门的汉语分析器,支持所有汉字字符集(ZHS16CGB231280 ZHS16GBK ZHT32EUC ZHT16BIG5 ZHT32TRIS ZHT16MSWIN950 ZHT16HKSCS UTF8 )。该分析器按字为单元来分析汉语句子。中国人民站起来了这句话,会被它分析成如下几个term: ‘中国国人人民民站站起,起来来了。可以看出,这种分析方法,实现算法很简单,并且能实现一网打尽,但效率则是差强人意。

n      chinese_lexer: 这是一个新的汉语分析器,只支持utf8字符集。上面已经看到,chinese vgram lexer这个分析器由于不认识常用的汉语词汇,因此分析的单元非常机械,像上面的民站站起在汉语中根本不会单独出现,因此这种term是没有意义的,反而影响效率。chinese_lexer的最大改进就是该分析器 能认识大部分常用汉语词汇,因此能更有效率地分析句子,像以上两个愚蠢的单元将不会再出现,极大 提高了效率。但是它只支持 utf8, 如果你的数据库是zhs16gbk字符集,则只能使用笨笨的那个Chinese vgram lexer.

如果不做任何设置,Oracle 缺省使用basic_lexer这个分析器。要指定使用哪一个lexer, 可以这样操作:

BEGIN

  ctx_ddl.create_preference ('my_lexer', 'chinese_vgram_lexer');

END;
/

其中my_lexer是分析器名。

 

二、建立全文索引

在建立intermedia索引时,指明所用的lexer:


CREATE INDEX  myindex ON mytable(mycolumn) indextype is ctxsys.context  
parameters('lexer my_lexer');

※个人体会:全文索引建立后,用pl/sql developer工具view table,在index这一栏是看不到索引信息的。

而本人在删除全文索引时遇到过一下报错:

SQL> drop index searchkeytbl_key;

drop index searchkeytbl_key

ORA-29868: cannot issue DDL on a domain index marked as LOADING

解决方法:

ORA-29868: cannot issue DDL on a domain index marked as LOADING
说明:在创建索引的时候断开、重启等导致索引中断没有执行成功,之后再drop或者rebuild等操作的时候都会报此错误
解决:只能drop index ind_name force强行删除,然后再重建


三、索引同步维护

用以下的两个job来完成(job要建在和表同一个用户下) :

VARIABLE jobno number;

BEGIN

DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.sync_index(''index_name'');',

SYSDATE, 'SYSDATE + (1/24/4)');

commit;

END;           //同步

 

VARIABLE jobno number;

BEGIN

DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.optimize_index(''myindex'',''FULL'');',

SYSDATE, 'SYSDATE + 1');

commit;         //优化

建完后手动运行下:

exec dbms_job.run(jobno);

※个人体会:运行job可能会有问题,此时可以单独运行索引,尝试一下

exec ctx_ddl.sync_index('index_name');

如果单独运行没有问题,则检查job是否写错或者当前操作的oracle数据库用户有无运行存储过程的权限

SQL> exec dbms_job.run(190);

begin dbms_job.run(190); end;

ORA-12011: execution of 1 jobs failed
ORA-06512: at "SYS.DBMS_IJOB", line 406
ORA-06512: at "SYS.DBMS_JOB", line 272
ORA-06512: at line 1

以上报错就是用户没有运行任何存储过程造成的,此时需要对用户加上这个权限:

SQL> grant execute any procedure to oracle_username; 

再看一下job的情况

select * from user_jobs;

 

四、测试

关联查询: select * from table_name where contains (column_name,'keyword') >0;

SQL> select * from searchkeytbl where type='城市' and contains (key,'杨浦') >0;

USERNAME             TYPE                                     KEY
-------------------- ---------------------------------------- --------------------------------------------------------------------------------
mujian80             城市                                     上海市杨浦区

 

五、问题

加全文索引遇到的问题(不断更新)

SQL> create index gh_ghname_idx on gh(ghname) indextype is ctxsys.context parameters('lexer gh_ghname_lexer');

create index gh_ghname_idx on gh(ghname) indextype is ctxsys.context parameters('lexer gh_ghname_lexer')

ORA-24795: Illegal COMMIT attempt made
ORA-29855: error occurred in the execution of ODCIINDEXCREATE routine
ORA-20000: Oracle Text error:
DRG-50857: oracle error in drvddl.IndexCreate
ORA-20000: Oracle Text error:
DRG-50857: oracle error in drvdml.MaintainKTab
ORA-24795: Illegal COMMIT attempt made
ORA-06512: at "CTXSYS.DRUE", line 160
ORA-06512: at "CTXSYS.TEXTINDEXMETHODS", line 364

 

 

To avoid the error, please use one of the following solutions

1. Don't use a 32k-blocksized tablespace to store the internal index objects
- or -
2. Download Patch 5596325 from Metalink and apply it as described in the README file.



通过案例学调优之--Oracle 全文索引

全文检索(oracle text) 

      Oracle Text使Oracle9i具备了强大的文本检索能力和智能化的文本管理能力,Oracle Text 是 Oracle9i 采用的新名称,在 oracle8/8i 中被称为 oracle intermedia text,oracle8 以前是 oracle context cartridge。Oracle Text 的索引和查找功能并不局限于存储在数据库中的数据。 它可以对存储于文件系统中的文档进行检索和查找,并可检索超过 150 种文档类型,包括 Microsoft Word、PDF和XML。Oracle Text查找功能包括模糊查找、词干查找(搜索mice 和查找 mouse)、通配符、相近性等查找方式,以及结果分级和关键词突出显示等。你甚至 可以增加一个词典,以查找搭配词,并找出包含该搭配词的文档。 

      Oracle text 需要为可检索的数据项建立索引,用户才能够通过搜索查找内容,索引进 程是根据管道建模的,在这个管道中,数据经过一系列的转换后,将其关键字会添加到索引 中。该索引进程分为多个阶段,如下图 

  

wKiom1Ru76bSaOvkAAC8Gbpz0iA684.jpg

1.数据检索(Datastore):只是将数据从数据存储(例如 web 页面、数据库大型对象或本 地文件系统)中取出,然后作为数据流传送到下一个阶段。 

2. 过滤(Filter):过滤器负责将各种文件格式的数据转换为纯文本格式,索引管道中的其 他组件只能处理纯文本数据,不能识别 Ms word 或 excel 等文件格式。 

3. 分段(Sectioner):分段器添加关于原始数据项结构的元数据。 

4. 词法分析(Lexer):根据数据项的语言将字符流分为几个字词。 5. 索引(Index):最后一个阶段将关键字添加到实际索引中。 

全文检索和普通检索的区别

      不使用Oracle text功能,当然也有很多方法可以在Oracle数据库中搜索文本,比如INSTR函数和LIKE操作:

1 、SELECT *FROM mytext WHERE INSTR (thetext, 'Oracle') > 0;

2 、SELECT * FROM mytext WHERE thetext LIKE '%Oracle%';

有很多时候,使用instr和like是很理想的, 特别是搜索仅跨越很小的表的时候。然而通过这些文本定位的方法将导致全表扫描,对资源来说消耗比较昂贵,而且实现的搜索功能也非常有限,因此对海量的文本数据进行搜索时,建议使用oralce提供的全文检索功能。

附:这里顺带记录一下INSTR和LIKE:

Oracle中,可以使用 Instr 函数对某个字符串进行判断,判断其是否含有指定的字符。其语法为:Instr(string, substring, position, occurrence)。

string:代表源字符串(写入字段则表示此字段的内容)。

substring:代表想从源字符串中查找的子串。

position:代表查找的开始位置,该参数可选的,默认为1。

occurrence:代表想从源字符中查找出第几次出现的substring,该参数也是可选的,默认为1。

position 的值为负数,那么代表从右往左进行查找。

instr和like的性能比较

其实从效率角度来看,谁能用到索引,谁的查询速度就会快。

like有时可以用到索引,例如:name like ‘李%’,而当下面的情况时索引会失效:name like ‘%李’。所以一般我们查找中文类似于‘%字符%’时,索引都会失效。与其他数据库不同的是,oracle支持函数索引。例如在name字段上建个instr索引,查询速度就比较快了,这也是为什么instr会比like效率高的原因。

注:instr(title,’手册’)>0 相当于like‘%手册%’

instr(title,’手册’)=0 相当于not like‘%手册%’

Oracle Text 索引原理 

    Oracle text 索引将文本中所有的字符转化成记号(token),如 www.taobao.com 会转化 成 www,taobao,com 这样的记号。
Oracle10g 里面支持四种类型的索引:

context、ctxcat、ctxrule、ctxxpath  

wKioL1Ru8E2yfosBAAIoUrpDBrU710.jpg

CONTEXT 

       用于对含有大量连续文本数据进行检索。支持 word、html、xml、text 等很多数据格式。支持范围(range)分区,支持并行创建索引(Parallel indexing)的索引类型。支持类型:VARCHAR2, CLOB, BLOB, CHAR, BFILE, XMLType, and URIType. 

DML 操作后,需要 CTX_DDL.SYNC_INDEX 手工同步索引 如果有查询包含多个词语,直接用空格隔开(如 oracle itpub) 

案例分析:

设置全文检索

步骤步骤一:检查和设置数据库角色

     首先检查数据库中是否有CTXSYS用户和CTXAPP脚色。如果没有这个用户和角色,意味着你的数据库创建时未安装intermedia功能(10G默认安装都有此用户和角色)。你必须修改数据库以安装这项功能。默认安装情况下,ctxsys用户是被锁定的,因此要先启用ctxsys的用户。

11:53:13 SYS@ prod >select username,account_status from dba_users where username like 'CTX%';
USERNAME                       ACCOUNT_STATUS
------------------------------ --------------------------------
CTXSYS                         EXPIRED & LOCKED

11:54:17 SYS@ prod >alter user ctxsys identified by oracle account unlock;
User altered.

11:55:07 SYS@ prod >select username,account_status from dba_users where username like 'CTX%';
USERNAME                       ACCOUNT_STATUS
------------------------------ --------------------------------
CTXSYS                         OPEN

12:00:13 SYS@ prod >select role from dba_roles
12:00:23   2   where role like 'CTX%';
ROLE
------------------------------
CTXAPP

步骤二:赋权

在ctxsys用户下,授予测试用户scott以下权限:

[oracle@RH6 ~]$ cat t.sql
GRANT resource, CONNECT, ctxapp TO scott;
GRANT EXECUTE ON ctxsys.ctx_cls TO scott;
GRANT EXECUTE ON ctxsys.ctx_ddl TO scott;
GRANT EXECUTE ON ctxsys.ctx_doc TO scott;
GRANT EXECUTE ON ctxsys.ctx_output TO scott;
GRANT EXECUTE ON ctxsys.ctx_query TO scott;
GRANT EXECUTE ON ctxsys.ctx_report TO scott;
GRANT EXECUTE ON ctxsys.ctx_thes TO scott;
GRANT EXECUTE ON ctxsys.ctx_ulexer TO scott;

11:58:04 SYS@ prod >@/home/oracle/t.sql
Grant succeeded.
Elapsed: 00:00:00.15
Grant succeeded.
Elapsed: 00:00:00.21
Grant succeeded.
Elapsed: 00:00:00.09
Grant succeeded.
Elapsed: 00:00:00.09
Grant succeeded.
Elapsed: 00:00:00.13
Grant succeeded.
Elapsed: 00:00:00.07
Grant succeeded.
Elapsed: 00:00:00.09
Grant succeeded.
Elapsed: 00:00:00.10
Grant succeeded.
Elapsed: 00:00:00.07

步骤三:设置词法分析器(lexer)

       Oracle实现全文检索,其机制其实很简单。即通过Oracle专利的词法分析器(lexer),将文章中所有的表意单元(Oracle 称为 term)找出来,记录在一组以dr$开头的表中,同时记下该term出现的位置、次数、hash值等信息。检索时,Oracle从这组表中查找相应的term,并计算其出现频率,根据某个算法来计算每个文档的得分(score),即所谓的‘匹配率’。而lexer则是该机制的核心,它决定了全文检索的效率。Oracle针对不同的语言提供了不同的lexer,而我们通常能用到其中的三个:

[cpp]  view plain  copy
 print ?
  1. basic_lexer:  
  2. 针对英语。它能根据空格和标点来将英语单词从句子中分离,还能自动将一些出现频率过高已经失去检索意义的单词作为‘垃圾’处理,如if,is等,具有较高的处理效率。但该lexer应用于汉语则有很多问题,由于它只认空格和标点,而汉语的一句话中通常不会有空格,因此,它会把整句话作为一个term,事实上失去检索能力。以‘中国人民站起来了’这句话为例,basic_lexer分析的结果只有一个term,就是‘中国人民站起来了’。此时若检索‘中国’,将检索不到内容。  
  3.   
  4. chinese_vgram_lexer:  
  5. 专门的汉语分析器,支持所有汉字字符集(ZHS16CGB231280 ZHS16GBK ZHT32EUC ZHT16BIG5 ZHT32TRIS ZHT16MSWIN950 ZHT16HKSCS UTF8 )。该分析器按字为单元来分析汉语句子。‘中国人民站起来了’这句话,会被它分析成如下几个term:‘中’,‘中国’,‘国人’,‘人民’,‘民站’,‘站起’,起来’,‘来了’,‘了’。可以看出,这种分析方法,实现算法很简单,并且能实现‘一网打尽’,但效率则是差强人意。  
  6.   
  7. chinese_lexer:  
  8. 这是一个新的汉语分析器,只支持utf8字符集。上面已经看到,chinese vgram lexer这个分析器由于不认识常用的汉语词汇,因此分析的单元非常机械,像上面的‘民站’,‘站起’在汉语中根本不会单独出现,因此这种term是没有意义的,反而影响效率。chinese_lexer的最大改进就是该分析器能认识大部分常用汉语词汇,因此能更有效率地分析句子,像以上两个愚蠢的单元将不会再出现,极大提高了效率。但是它只支持utf8,如果你的数据库是zhs16gbk字符集,则只能使用笨笨的那个Chinese vgram lexer。如果不做任何设置,Oracle缺省使用basic_lexer这个分析器。  
[java]  view plain  copy
 print ?
  1. 12:05:01 SYS@ prod >select userenv('language') from dual;  
  2. USERENV('LANGUAGE')  
  3. ----------------------------------------------------  
  4. AMERICAN_AMERICA.ZHS16GBK  
  5.   
  6. 12:08:05 SCOTT@ prod >desc ctx_ddl  
  7. PROCEDURE CREATE_PREFERENCE  
  8.  Argument Name                  Type                    In/Out Default?  
  9.  ------------------------------ ----------------------- ------ --------  
  10.  PREFERENCE_NAME                VARCHAR2                IN  
  11.  OBJECT_NAME                    VARCHAR2                IN  
  12.    
  13. 12:12:25 SCOTT@ prod >EXEC ctx_ddl.create_preference ('my_lexer''chinese_vgram_lexer');  
  14. PL/SQL procedure successfully completed.  
  15.   
  16. 创建表  
  17. 12:13:15 SCOTT@ prod >CREATE TABLE textdemo(  
  18. 12:15:47   2       id NUMBER NOT NULL PRIMARY KEY,  
  19. 12:15:47   3       book_author varchar2(100),--作者  
  20. 12:15:47   4       publish_time DATE,--发布日期  
  21. 12:15:47   5       title varchar2(400),--标题  
  22. 12:15:47   6       book_abstract varchar2(2000),--摘要  
  23. 12:15:47   7       path varchar2(200)--路径  
  24. 12:15:47   8  );  
  25. Table created.  
插入数据
14:53:20 SCOTT@ prod >insert into textdemo values (10,'luyao',sysdate,'pingfan de world','zhen shi de gushi','/home/1.txt');
1 row created.

14:54:32 SCOTT@ prod >commit;

步骤四:在book_abstract字段建立索引使用刚刚设置的ORATEXT_LEXER :chinese_vgram_lexer作为分析器。

12:16:15 SCOTT@ prod >CREATE INDEX demo_abstract ON textdemo(book_abstract) indextype IS ctxsys.context parameters('lexer my_LEXER');  

之后如上所述多出很多dr$开头的表和索引,系统会创建四个相关的表:
DR$DEMO_ABSTRACT$I(分词后的TOKEN表)
DR$DEMO_ABSTRACT$K
DR$DEMO_ABSTRACT$N 
DR$DEMO_ABSTRACT$R
14:56:16 SCOTT@ prod >select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
BONUS                          TABLE
DEPT                           TABLE
DR$DEMO_ABSTRACT$I             TABLE
DR$DEMO_ABSTRACT$K             TABLE
DR$DEMO_ABSTRACT$N             TABLE
DR$DEMO_ABSTRACT$R             TABLE
EMP                            TABLE
SALGRADE                       TABLE
TEXTDEMO                       TABLE

9 rows selected.
14:56:36 SCOTT@ prod >desc DR$DEMO_ABSTRACT$I
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 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

14:57:45 SCOTT@ prod >desc DR$DEMO_ABSTRACT$K
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 DOCID                                                                      NUMBER(38)
 TEXTKEY                                                           NOT NULL ROWID

14:57:57 SCOTT@ prod >desc DR$DEMO_ABSTRACT$N
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 NLT_DOCID                                                         NOT NULL NUMBER(38)
 NLT_MARK                                                          NOT NULL CHAR(1)

14:58:11 SCOTT@ prod >desc DR$DEMO_ABSTRACT$R
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 ROW_NO                                                                     NUMBER(3)
 DATA                                                                       BLOB
 
 14:58:26 SCOTT@ prod >select index_name,index_type,table_name from user_indexes;

INDEX_NAME                     INDEX_TYPE                  TABLE_NAME
------------------------------ --------------------------- ------------------------------
DEMO_ABSTRACT                  DOMAIN                      TEXTDEMO
SYS_C0013418                   NORMAL                      TEXTDEMO
PK_EMP                         NORMAL                      EMP
SYS_IL0000076525C00002$$       LOB                         DR$DEMO_ABSTRACT$R
SYS_IOT_TOP_76528              IOT - TOP                   DR$DEMO_ABSTRACT$N
SYS_IOT_TOP_76523              IOT - TOP                   DR$DEMO_ABSTRACT$K
SYS_IL0000076520C00006$$       LOB                         DR$DEMO_ABSTRACT$I
DR$DEMO_ABSTRACT$X             NORMAL                      DR$DEMO_ABSTRACT$I
PK_DEPT                        NORMAL                      DEPT

9 rows selected.

下面的语句可以查看索引创建过程中是否发生了错误:

[cpp]  view plain  copy
 print ?
  1. SELECT * FROM ctx_USER_index_errors  
  2.   
  3. 附:对于建立索引的类型(例如ctxsys.context),包括四种:context,ctxcat,ctxrule,ctxxpath。  
  4. CONTEXT用于对含有大量连续文本数据进行检索。支持word、html、xml、text等很多数据格式。支持范围(range)分区,支持并行创建索引(Parallel indexing)的索引类型。  
  5. 支持类型:VARCHAR2, CLOB, BLOB, CHAR, BFILE, XMLType, and URIType.DML。操作后,需要CTX_DDL.SYNC_INDEX手工同步索引如果有查询包含多个词语,直接用空格隔开(如 oracle itpub)。  
  6.   
  7. 查询标识符CONTAINS  
  8. CTXCAT适用于混合查询语句(如查询条件包括产品id,价格,描述等)。适合于查询较小的具有一定结构的文本段。具有事务性。DML 操作后,索引会自动进行同步。  
  9. 操作符:and,or,>,;<, =,between,in  
  10. 查询标识符CATSEARCH  
  11. CTXRULE查询标识符MATCHES。  
  12. CTXXPATH(这两个索引没有去更多搜索相关内容)  
  13. 一般来说我们建立CONTEXT类型的索引(CONTAINS来查询)。  

步骤五:查询测试

查看执行计划
15:04:36 SCOTT@ prod >r
  1* select * from textdemo where contains(book_abstract,'gushi')>0

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
Plan hash value: 2570915478

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     1 |  1392 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEXTDEMO      |     1 |  1392 |     4   (0)| 00:00:01 |
|*  2 |   DOMAIN INDEX              | DEMO_ABSTRACT |       |       |     4   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("CTXSYS"."CONTAINS"("BOOK_ABSTRACT",'gushi')>0)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
         29  recursive calls
          0  db block gets
         33  consistent gets
          0  physical reads
          0  redo size
        796  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

15:04:37 SCOTT@ prod >

通过sql trace查看详细计划(部分内容)

SQL ID: 2rsr1z6zkp24p
Plan Hash: 2570915478
select *
from
 textdemo where contains(book_abstract,:"SYS_B_0")>:"SYS_B_1"

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.01       0.01          0        250          0           0
Fetch        2      0.00       0.00          0          2          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.01       0.01          0        252          0           1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 101

Rows     Row Source Operation
-------  ---------------------------------------------------
      1  TABLE ACCESS BY INDEX ROWID TEXTDEMO (cr=12 pr=0 pw=0 time=0 us cost=4 size=1392 card=1)
      1   DOMAIN INDEX  DEMO_ABSTRACT (cr=11 pr=0 pw=0 time=0 us cost=4 size=0 card=0)
      
declare
     cost sys.ODCICost := sys.ODCICost(NULL, NULL, NULL, NULL);
     arg0 VARCHAR2(1) := null;

    begin
      :1 := "CTXSYS"."TEXTOPTSTATS".ODCIStatsFunctionCost(
                     sys.ODCIFuncInfo('CTXSYS',
                            'CTX_CONTAINS',
                            'TEXTCONTAINS',
                            2),
                     cost,
                     sys.ODCIARGDESCLIST(sys.ODCIARGDESC(2, 'TEXTDEMO', 'SCOTT', '"BOOK_ABSTRACT"', NULL, NULL, NULL), sys.ODCIARG
DESC(1, NULL, NULL, NULL, NULL, NULL, NULL))
                     , arg0, :5,
                     sys.ODCIENV(:6,:7,:8,:9));
      if cost.CPUCost IS NULL then
        :2 := -1.0;
      else
        :2 := cost.CPUCost;
      end if;
      if cost.IOCost IS NULL then
        :3 := -1.0;
      else
        :3 := cost.IOCost;
      end if;
      if cost.NetworkCost IS NULL then
        :4 := -1.0;
      else
        :4 := cost.NetworkCost;
      end if;
      exception
        when others then
          raise;
    end;

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        2      0.00       0.00          0          0          0           0
Execute      2      0.00       0.00          0         18          0           2
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0         18          0           2

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 101     (recursive depth: 1)

全文索引和DML操作

Insert 操作:

15:19:21 SCOTT@ prod >insert into textdemo values (20,'huoda',sysdate,'musilin de zangli','meili de rensheng','/home/2.txt');
1 row created.
15:20:10 SCOTT@ prod >commit;

15:21:35 SCOTT@ prod >select id,BOOK_ABSTRACT from textdemo where BOOK_ABSTRACT like '%rensheng%'
        ID BOOK_ABSTRACT
---------- --------------------------------------------------
        20 meili de rensheng
        
15:23:12 SCOTT@ prod >set autotrace on
15:23:38 SCOTT@ prod >select id,BOOK_ABSTRACT from textdemo where contains(BOOK_ABSTRACT,'rensheng')>0
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 2570915478
---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     1 |  1027 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEXTDEMO      |     1 |  1027 |     4   (0)| 00:00:01 |
|*  2 |   DOMAIN INDEX              | DEMO_ABSTRACT |       |       |     4   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("CTXSYS"."CONTAINS"("BOOK_ABSTRACT",'rensheng')>0)
Note
-----
   - dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
         23  recursive calls
          0  db block gets
         33  consistent gets
          0  physical reads
          0  redo size
        349  bytes sent via SQL*Net to client
        404  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed
15:26:40 SYS@ prod >select * from ctxsys.dr$pending;
   PND_CID    PND_PID PND_ROWID          PND_TIMES P
---------- ---------- ------------------ --------- -
      1082          0 AAASrlAAEAAAAI1AAB 21-NOV-14 N
15:26:26 SCOTT@ prod >alter index demo_abstract rebuild parameters('sync');
Index altered.
15:30:10 SCOTT@ prod >select id,BOOK_ABSTRACT from textdemo where contains(BOOK_ABSTRACT,'rensheng')>0;
        ID BOOK_ABSTRACT
---------- --------------------------------------------------
        20 meili de rensheng

 在做Insert操作时,Oracle会把一条信息放入到CTXSYS.DR$PENDING表里,必须手工进行同步才能更新全文索引。


Delete 操作:


15:30:37 SCOTT@ prod >delete from textdemo where id=20;
1 row deleted.

15:33:06 SCOTT@ prod >select id,BOOK_ABSTRACT from textdemo;
        ID BOOK_ABSTRACT
---------- --------------------------------------------------
        10 zhen shi de gushi

15:33:39 SCOTT@ prod >rollback;
Rollback complete.

15:33:50 SCOTT@ prod >select id,BOOK_ABSTRACT from textdemo;
        ID BOOK_ABSTRACT
---------- --------------------------------------------------
        10 zhen shi de gushi
        20 meili de rensheng

   Delete 操作后,索引会立刻更新。

Update 操作:

15:38:14 SCOTT@ prod >update textdemo set BOOK_ABSTRACT='meili de gushi' where id=20;
1 row updated.

15:39:48 SYS@ prod >select * from ctxsys.dr$delete;
no rows selected

15:39:59 SYS@ prod >select * from ctxsys.dr$pending;
no rows selected

15:43:03 SCOTT@ prod >select id,BOOK_ABSTRACT from textdemo where contains(BOOK_ABSTRACT,'gushi')>0;
        ID BOOK_ABSTRACT
---------- --------------------------------------------------
        10 zhen shi de gushi

15:43:14 SCOTT@ prod >alter index demo_abstract rebuild parameters('sync');
Index altered.

15:43:39 SCOTT@ prod >select id,BOOK_ABSTRACT from textdemo where contains(BOOK_ABSTRACT,'gushi')>0;
        ID BOOK_ABSTRACT
---------- --------------------------------------------------
        10 zhen shi de gushi
        20 meili de gushi

     对于update操作,应该是包含了Delete和Insert的操作,需要手工同步后才能更新索引。

对多字段建立全文索引

很多时候需要从多个文本字段中查询满足条件的记录,这时就需要建立针对多个字段的全文索引,例如需要从pmhsubjects(专题表)的 subjectname(专题名称)和briefintro(简介)上进行全文检索,则需要按以下步骤进行操作:

建立多字段索引的preference,以ctxsys登录,并执行:

BEGIN

ctx_ddl.create_preference('ctx_demo_abstract_title','MULTI_COLUMN_DATASTORE');

END;

建立preference对应的字段值(以ctxsys登录) 对应title path book_abstract三个字段建立索引:


BEGIN

ctx_ddl.set_attribute('ctx_demo_abstract_title ','columns','title,path');

END;

建立全文索引:

CREATE INDEX demo_abstract_title ON textdemo(book_abstract) indextype IS ctxsys.context parameters(' DATASTORE ctxsys. ctx_demo_ abstract_title lexer ORATEXT_LEXER');  

commit;

测试

SELECT score(20),t.* FROM textdemo t WHERE contains(book_abstract,'移动城堡 or 俄罗斯',20)>0;

对大字段进行检索测试

CREATE TABLE mytable(id NUMBER PRIMARY KEY, docs CLOB);

INSERT INTO mytable VALUES(111555,'this text will be indexed');

INSERT INTO mytable VALUES(111556,'this is a direct_datastore example');

Commit;

 

CREATE INDEX myindex ON mytable(docs)

indextype IS ctxsys.context

parameters ('datastore ctxsys.default_datastore');

 

SELECT * FROM mytable WHERE contains(docs, 'text') > 0;




1 创建数据存储定义(Datastore),使用多列数据存储在多列上创建全文索引

BEGIN
     CTX_DDL.CREATE_PREFERENCE(
'INFOGRID_COM_DATASTORE','MULTI_COLUMN_DATASTORE');

CTX_DDL.SET_ATTRIBUTE('INFOGRID_COM_DATASTORE','columns','NAME,ADDRESS,BUSINESS_ZONE,FAREN,FUND,INTRODUCTION');

END;

2.创建词法分析器(Lexer

BEGIN
    CTX_DDL.CREATE_PREFERENCE(
'INFOGRID_LEXER''CHINESE_LEXER');
END;

 

3.创建全文索引(索引在DML提交后自动同步更新)

CREATE INDEX INFOGRID_COM_FULL_IDX ON g2b_com(NAME)
INDEXTYPE  IS  CTXSYS.CONTEXT
PARAMETERS (
   
'LEXER INFOGRID_LEXER
    DATASTORE INFOGRID_COM_DATASTORE
    SYNC (ON COMMIT)' 
--使用实时同步(DML提交时同步全文索引)
)

--手工同步索引(如果使用自动同步,这步可省略)

begin
ctx_ddl.sync_index(
'INFOGRID_COM_FULL_IDX');
end;

 

4.使用全文索引查询(按照出现频率排序)

select score(0),t.* from g2b_com t where contains(NAME,'条件一,条件二',0)>0 order by score(0desc

 

5.删除全文索引(删除词法分析器,删除数据存储定义,删除索引)

begin
ctx_ddl.drop_preference(
'INFOGRID_COM_DATASTORE');--删除数据储存定义DataStore

ctx_ddl.drop_preference('INFOGRID_LEXER');--删除词法分析器
end;
drop index INFOGRID_COM_FULL_IDX;
--删除索引






ORA-06553: PLS-907: cannot load library unit XDB.XDB_FUNCIMPL during export  

文档 ID:  785728.1  类型:  PROBLEM  Modified Date:  25-FEB-2009  状态:  REVIEWED

In this Document
  Symptoms
  Cause
  Solution
  References




Applies to:Oracle Server Enterprise Edition - Version: 10.1.0.2 to 10.2.0.4
This problem can occur on any platform.
SymptomsExport is failing with below errors:
    
        EXP-00056: ORACLE error 29900 encountered
        ORA-29900: operator binding does not exist
        ORA-06540: PL/SQL: compilation error
        ORA-06553: PLS-907: cannot load library unit XDB.XDB_FUNCIMPL (referenced by XDB.UNDER_PATH)
        EXP-00000: Export terminated unsuccessfully Cause

It seems you have some invalid objects in XDB schema or XDB installation is INVALID.

Solution-- check DBA Registry for status of installed components

set pages 1000
column comp_id format A10
column version like comp_id
column comp_name format A35
col status for a15
select comp_id, status, version, comp_name from dba_registry order by 1;

-- check for invalid XDB objects

col owner for a15
col object_name for a30
col object_type for a30

select owner,object_name,object_type from dba_objects
where status != 'VALID'
and wner = 'XDB'
/

You can try to recompile all invalid objects using:

SQL> connect / as sysdba
SQL> @?/rdbms/admin/utlrp.sql

Then check the invalid XDB objects again. If there are no invalid XDB objects then try the export again.
If you still have invalid XDB objects which cannot be compiled then you may have to re-install XDB as described in the note specified below:


Note 243554.1 - How to Deinstall and Reinstall XML Database (XDB)

References Note 243554.1  - How to Deinstall and Reinstall XML Database (XDB)






About Me

...............................................................................................................................

● 本文整理自网络

● 本文在itpub(http://blog.itpub.net/26736162)、博客园(http://www.cnblogs.com/lhrbest)和个人微信公众号(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/

● 本文博客园地址:http://www.cnblogs.com/lhrbest

● 本文pdf版及小麦苗云盘地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 数据库笔试面试题库及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● QQ群:230161599     微信群:私聊

● 联系我请加QQ好友(646634621),注明添加缘由

● 于 2017-05-09 09:00 ~ 2017-05-30 22:00 在魔都完成

● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

● 版权所有,欢迎分享本文,转载请保留出处

...............................................................................................................................

拿起手机使用微信客户端扫描下边的左边图片来关注小麦苗的微信公众号:xiaomaimiaolhr,扫描右边的二维码加入小麦苗的QQ群,学习最实用的数据库技术。


DBA笔试面试讲解
欢迎与我联系

目录
相关文章
|
自然语言处理 Oracle 关系型数据库
|
SQL Web App开发 存储
|
SQL Oracle 关系型数据库
ORACLE中文全文索引
1.oracle text 首先这里说oracle 全文检索,是针对我机器上的oracle 10g版本的。
1216 0
|
存储 Oracle 关系型数据库
Oracle Text(全文索引)
Oracle 全文索引 前言:        Oracle从7.3开始支持全文检索,即用户可以使用Oracle服务器的上下文(ConText)选项完成基于文本的查询。
1298 0
|
Oracle 关系型数据库 索引
oracle 创建空间全文索引失败
If you ever want to create or rebuild an oracle spatial index in another schema, you need to m...
882 0
|
自然语言处理 Oracle 关系型数据库
Oracle全文索引设置步骤
导读:   已有几个项目组开始使用oracle的全文索引。Oracle的词法分析器针对ZHS16GBK字符集的词法分析尚不够智能,只能机械地以字为单元进行匹配。
915 0
|
2月前
|
存储 Oracle 关系型数据库
Oracle数据库的应用场景有哪些?
【10月更文挑战第15天】Oracle数据库的应用场景有哪些?
202 64
|
19天前
|
存储 Oracle 关系型数据库
数据库数据恢复—ORACLE常见故障的数据恢复方案
Oracle数据库常见故障表现: 1、ORACLE数据库无法启动或无法正常工作。 2、ORACLE ASM存储破坏。 3、ORACLE数据文件丢失。 4、ORACLE数据文件部分损坏。 5、ORACLE DUMP文件损坏。
66 11
|
1月前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
|
1月前
|
存储 Oracle 关系型数据库
oracle数据恢复—Oracle数据库文件大小变为0kb的数据恢复案例
存储掉盘超过上限,lun无法识别。管理员重组存储的位图信息并导出lun,发现linux操作系统上部署的oracle数据库中有上百个数据文件的大小变为0kb。数据库的大小缩水了80%以上。 取出&并分析oracle数据库的控制文件。重组存储位图信息,重新导出控制文件中记录的数据文件,发现这些文件的大小依然为0kb。