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

通过案例学调优之--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 需要为可检索的数据项建立索引,用户才能够通过搜索查找内容,索引进 程是根据管道建模的,在这个管道中,数据经过一系列的转换后,将其关键字会添加到索引 中。该索引进程分为多个阶段,如下图

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

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 [email protected] prod >select username,account_status from dba_users where username like ‘CTX%‘;
USERNAME                       ACCOUNT_STATUS
------------------------------ --------------------------------
CTXSYS                         EXPIRED & LOCKED

11:54:17 [email protected] prod >alter user ctxsys identified by oracle account unlock;
User altered.

11:55:07 [email protected] prod >select username,account_status from dba_users where username like ‘CTX%‘;
USERNAME                       ACCOUNT_STATUS
------------------------------ --------------------------------
CTXSYS                         OPEN

12:00:13 [email protected] prod >select role from dba_roles
12:00:23   2   where role like ‘CTX%‘;
ROLE
------------------------------
CTXAPP

步骤二:赋权

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

[[email protected] ~]$ 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 [email protected] 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,而我们通常能用到其中的三个:

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这个分析器。
12:05:01 [email protected] prod >select userenv(‘language‘) from dual;
USERENV(‘LANGUAGE‘)
----------------------------------------------------
AMERICAN_AMERICA.ZHS16GBK

12:08:05 [email protected] prod >desc ctx_ddl
PROCEDURE CREATE_PREFERENCE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 PREFERENCE_NAME                VARCHAR2                IN
 OBJECT_NAME                    VARCHAR2                IN
 
12:12:25 [email protected] prod >EXEC ctx_ddl.create_preference (‘my_lexer‘, ‘chinese_vgram_lexer‘);
PL/SQL procedure successfully completed.

创建表
12:13:15 [email protected] prod >CREATE TABLE textdemo(
12:15:47   2       id NUMBER NOT NULL PRIMARY KEY,
12:15:47   3       book_author varchar2(100),--作者
12:15:47   4       publish_time DATE,--发布日期
12:15:47   5       title varchar2(400),--标题
12:15:47   6       book_abstract varchar2(2000),--摘要
12:15:47   7       path varchar2(200)--路径
12:15:47   8  );
Table created.
插入数据
INSERT INTO textdemo VALUES(1,‘宫琦峻‘,to_date(‘2008-10-07‘,‘yyyy-mm-dd‘),‘ 移动城堡‘,‘故事发生在19世纪末的欧洲,善良可爱的苏菲被恶毒的女巫施下魔咒,从18岁的女孩变成90岁的婆婆,孤单无助的她无意中走入镇外的移动城堡,据说它的主人哈尔以吸取女孩的灵魂为乐,但是事情并没有人们传说的那么可怕,性情古怪的哈尔居然收留了苏菲,两个人在四脚的移动城堡中开始了奇妙的共同生活,一段交织了爱与痛、乐与悲的爱情故事在战火中悄悄展开‘,‘E:\textsearch\moveingcastle.doc‘);  
 
INSERT INTO textdemo VALUES(2,‘莫贝克曼贝托夫‘,to_date(‘2008-10-07‘,‘yyyy-mm-dd‘),‘ ***转弯‘,‘这部由俄罗斯导演提莫贝克曼贝托夫执导的影片自6 月末在北美上映以来,已经在全球取得了超过3亿美元的票房收入。在亚洲上映后也先后拿下日本、韩国等地的票房冠军宝座。虽然不少网友在此之前也相继通过各种渠道接触到本片,但相信影片凭着在大银幕上呈现出的超酷的视听效果,依然能够吸引大量影迷前往影院捧场。‘,‘E:\textsearch\catch.pdf‘);  
 
INSERT INTO textdemo VALUES(3,‘袁泉‘,to_date(‘2008-10-07‘,‘yyyy-mm-dd‘),‘主演吴彦祖和袁泉现身‘,‘电影《如梦》在上海同乐坊拍摄,主演吴彦祖和袁泉现身。由于是深夜拍摄,所以周围并没有过多的fans注意到,给了剧组一个很清净的拍摄环境,站在街头的袁泉低着头,在寒冷的夜里看上去还真有些像女鬼,令人毛骨悚然。‘,‘E:\textsearch\dream.txt‘);

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

CREATE INDEX demo_abstract ON textdemo(book_abstract) indextype IS ctxsys.context parameters(‘lexer ORATEXT_LEXER‘);  
commit;
之后如上所述多出很多dr$开头的表和索引,系统会创建四个相关的表:
DR$DEMO_ABSTRACT$I(分词后的TOKEN表)
DR$DEMO_ABSTRACT$K
DR$DEMO_ABSTRACT$N 
DR$DEMO_ABSTRACT$R

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

SELECT * FROM ctx_USER_index_errors

附:对于建立索引的类型(例如ctxsys.context),包括四种:context,ctxcat,ctxrule,ctxxpath。
CONTEXT用于对含有大量连续文本数据进行检索。支持word、html、xml、text等很多数据格式。支持范围(range)分区,支持并行创建索引(Parallel indexing)的索引类型。
支持类型:VARCHAR2, CLOB, BLOB, CHAR, BFILE, XMLType, and URIType.DML。操作后,需要CTX_DDL.SYNC_INDEX手工同步索引如果有查询包含多个词语,直接用空格隔开(如 oracle itpub)。

查询标识符CONTAINS
CTXCAT适用于混合查询语句(如查询条件包括产品id,价格,描述等)。适合于查询较小的具有一定结构的文本段。具有事务性。DML 操作后,索引会自动进行同步。
操作符:and,or,&gt,;<, =,between,in
查询标识符CATSEARCH
CTXRULE查询标识符MATCHES。
CTXXPATH(这两个索引没有去更多搜索相关内容)
一般来说我们建立CONTEXT类型的索引(CONTAINS来查询)。

步骤五:查询测试

--查询或
SELECT score(20),t.* FROM textdemo t WHERE contains(book_abstract,‘移动城堡 or 俄罗斯‘,20)>0;  
SELECT score(20),t.* FROM textdemo t WHERE contains(book_abstract,‘移动城堡 or 欧洲‘,20)>0;
--基本查询
SELECT score(20),t.* FROM textdemo t WHERE contains(book_abstract,‘移动城堡‘,20)>0;
--查询包含多个词语and测试通过
SELECT score(20),t.* FROM textdemo t WHERE contains(book_abstract,‘移动城堡 and 欧洲‘,20)>0;
测试通过。

对多字段建立全文索引

很多时候需要从多个文本字段中查询满足条件的记录,这时就需要建立针对多个字段的全文索引,例如需要从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;

时间: 2024-10-08 07:40:52

通过案例学调优之--Oracle 全文索引的相关文章

通过案例学调优之--Oracle参数(db_file_multiblock_read_count)

通过案例学调优之--Oracle参数(db_file_multiblock_read_count) 应用环境: 操作系统: RedHat EL55 Oracle:   Oracle 10gR2   Oracle DB_FILE_MULTIBLOCK_READ_COUNT是Oracle比较重要的一个全局性参数,可以影响系统级别及sessioin级别.主要是用于设置最小化表扫描时Oracle一次按顺序能够读取的数据块数.通常情况下,我们看到top events中的等待事件db file scatte

通过案例学调优之--Oracle Cluster Table

通过案例学调优之--Oracle Cluster Table About Clusters A cluster provides an optional method of storing table data. A cluster is made up of a group of tables that share the same data blocks. The tables are grouped together because they share common columns an

通过案例学调优之--Oracle Time Model(时间模型)

通过案例学调优之--Oracle Time Model(时间模型) 数据库时间  优化不仅仅是缩短等待时间.优化旨在缩短最终用户响应时间和(或)尽可能减少每个请求占用的平均资源.有时这些目标可同时实现,而有时则需要进行折衷(如在并行查询时).通常可以认为,优化就是避免以浪费的方式占用或保留资源. 对数据库发出的任何请求都由两个不同的段组成:等待时间(数据库等待时间)和服务时间(数据库 CPU 时间).等待时间是各种数据库实例资源的所有等待时间的总和.CPU 时间是实际处理请求时消耗的时间的总和.

通过案例学调优之--Oracle中null使用索引

通过案例学调优之--Oracle中null使用索引  默认情况下,Oracle数据库,null在Index上是不被存储的,当在索引列以"is null"的方式访问时,无法使用索引:本案例,主要向大家演示如何在存在null的索引列上,使用"is null"访问索引. 案例分析: 1.建立表和普通索引 13:52:23 [email protected] prod >create table t2 (x int,y int); Table created. 14:

通过案例学调优之--Oracle数据块(block)

数据块概述Oracle对数据库数据文件(datafile)中的存储空间进行管理的单位是数据块(data block).数据块是数据库中最小的(逻辑)数据单位.与数据块对应的,所有数据在操作系统级的最小物理存储单位是字节(byte).每种操作系统都有一个被称为块容量(block size)的参数.Oracle每次获取数据时,总是访问整个数(Oracle)数据块,而不是按照操作系统块的容量访问数据. 数据库中标准的数据块(data block)容量是由初始化参数 DB_BLOCK_SIZE 指定的.

通过案例学调优之--AWR BaseLine管理

通过案例学调优之--AWR BaseLine管理 BaseLine Baseline 是指一个特定时间段内的性能数据,保留这些数据是为了在性能问题产生时与其他类似的工作负载时间段进行比较.Baseline 中包含的快照将从自动 AWR 清理进程中排除,并无限期的保留. 在 Oracle Database 中存在多种类型的 baseline:      Fixed Baseline:fixed baseline 表示的是您指定的一个固定的.连续的时间段.在创建 fixed baseline 之前,

通过案例学调优之--SQL Profile

通过案例学调优之--SQL Profile 一.什么是SQL Profile(概要) SQL Profile在性能优化中占有一个重要的位置. MOS里这么描述SQL Profile: SQL Profile是10g中的新特性,作为自动SQL调整过程的一部分,由Oracle企业管理器来管理.除了OEM,SQL Profile可以通过DBMS_SQLTUNE包来进行管理. 查询优化器有时候会因为缺乏足够的信息,而对一条SQL语句做出错误的估计,生成糟糕的执行计划.而自动SQL调整通过SQL概要分析来

通过案例学调优之--AWR基本概念

通过案例学调优之--AWR基本概念 一.Automatic Workload Repository 概念详解 Automatic Workload Repository (AWR) 收集.处理和维护用于问题诊断的性能统计信息.该数据既存在于数据块中,也存在于内存中.AWR 收集的数据可以通过报告和视图进行查看. AWR 处理和收集的统计信息包括: 1.确定数据块 segment 访问路径和使用情况的对象统计信息 2.基于数据库活动的时间使用情况的时间模型统计信息,可在 V$SYS_TIME_MO

通过案例学调优之--模拟buffer busy waits事件

通过案例学调优之--模拟buffer busy waits事件 buffer busy waits等待事件     Wait occurs when a session attempts to access a block in memory, is denied and must wait until the buffer becomes available. This event happens because a buffer is either being read into the b