oracle全文索引之如何实现查询


oracle全文索引有很多种查询方式,最常用的可能是contains。下面就contains简单阐述oracle全文检索执行查询的运行机制。



先介绍两个脚本:begin_trace、end_trace是我为了方便查看trace文件写的脚本。代码如下:

-- run in SQL*Plus --
-- begin_trace ----
set termout off
set heading off
set verify off
set feedback off
alter session set timed_statistics=true;
alter session set events '10046 trace name context forever,level 12';

-- run in SQL*Plus --
-- end_trace ----
alter session set events '10046 trace name context off';
column trace_file_name new_val f
column tk_name new_val tk
select
d.value||b.is_win||lower(rtrim(i.instance, chr(0)))||'_ora_'||p.spid||'.trc' trace_file_name
from
( select p.spid
from v$mystat m,v$session s,v$process p
where m.statistic# = 1 and s.sid = m.sid and p.addr = s.paddr) p,
( select t.instance from v$thread t,v$parameter v
where v.name = 'thread' and (v.value = 0 or t.thread# = to_number(v.value))) i,
( select value from v$parameter where name = 'user_dump_dest') d,
(select DECODE(count(*),0,'/','') is_win from v$version where upper(banner) like '%WINDOWS%') b;

select value||b.is_win||'tk.prf' tk_name
from v$parameter v ,
(select DECODE(count(*),0,'/','') is_win from v$version where upper(banner) like '%WINDOWS%') b
where name = 'user_dump_dest';
set termout on
set heading on
set verify on
set feedback off
host tkprof &f &tk
edit &tk

实验一:直接查询
suk@oracle9i> @begin_trace
suk@oracle9i> select * from t_domain where contains(doc,'shenzhen') >0;

5 this is shenzhen
suk@oracle9i> @end_trace

产?膖race内容比较多,这里把最主要的地方摘取出来:

--发出查询
select *
from
t_domain where contains(doc,'shenzhen') >0

BEGIN :p := CTX_QUERY.PREFERENCE;END;


SELECT /*+ INDEX(i) */ TOKEN_FIRST,TOKEN_LAST,TOKEN_COUNT,ROWID
FROM
"SUK"."DR$IDX_DOMAIN$I" i WHERE TOKEN_TEXT = :word AND TOKEN_TYPE = :wtype
ORDER BY TOKEN_TEXT, TOKEN_TYPE, TOKEN_FIRST


SELECT TOKEN_INFO
FROM
"SUK"."DR$IDX_DOMAIN$I" WHERE ROWID = :rid

select data
from
"SUK"."DR$IDX_DOMAIN$R" where row_no = :row_no


从trace中的sql可以知道查询的执行流程:
1、首先用户发出包含contains的查询
2、根据关键字在$I表中得到满足条件的rowid
3、根据上一步得到的rowid得到TOKEN_INFO,TOKEN_INFO中包含了满足条件的docid、row_no等信息
4、oracle根据这些信息在$R表中取出基表中满足查询条件的rowid,然后返回给原始的查询语句
5、最终oracle根据这些rowid取出用户需要的数据。
---------------------------------------------------------------

实验二、先删除(或者更新),再查询
suk@oracle9i> delete from t_domain where rownum=1;

已删除 1 行。

suk@oracle9i> @begin_trace
suk@oracle9i> select * from t_domain where contains(doc,'shenzhen') >0;
suk@oracle9i> @end_trace
注意:不要提交

摘录trace中主要的sql如下:
select *
from
t_domain where contains(doc,'shenzhen') >0


SELECT DEL_DOCID
FROM
DR$DELETE WHERE DEL_IDX_ID = :iid and DEL_ixp_id = :ipid ORDER BY DEL_IDX_ID,
DEL_DOCID DESC


BEGIN :p := CTX_QUERY.PREFERENCE;END;


SELECT /*+ INDEX(i) */ TOKEN_FIRST,TOKEN_LAST,TOKEN_COUNT,ROWID
FROM
"SUK"."DR$IDX_DOMAIN$I" i WHERE TOKEN_TEXT = :word AND TOKEN_TYPE = :wtype
ORDER BY TOKEN_TEXT, TOKEN_TYPE, TOKEN_FIRST


SELECT TOKEN_INFO
FROM
"SUK"."DR$IDX_DOMAIN$I" WHERE ROWID = :rid

从trace中的sql可以看出,这个执行流程和实验一不一样。
在这个实验中,多了从DR$DELETE中查找docid这一步。
我们知道,DR$DELETE是保存当前会话在修改数据而没有提交时被删除的docid。
1、首先用户发出包含contains的查询
2、如果发生了数据删除(更新),oracle先从DR$DELETE中得到在当前会话中被删除的docid
3、再根据关键字在$I表中得到满足条件的rowid
4、根据上一步得到的rowid得到TOKEN_INFO,TOKEN_INFO中包含了满足条件的docid、row_no等信息
5、在上一步得到的结果中排除从DR$DELETE得到的docid。
6、oracle根据这些信息在$R表中取出基表中满足查询条件的rowid,然后返回给原始的查询语句
7、最终oracle根据这些rowid取出用户需要的数据。

其中:第四步在trace中并没有得到反映,但从oracle官方文档和实际测试中得到验证。

不明之处:
1、$K表会在什么情况下?
oracle文档说到:
There are two sorts of index lookup used in interMedia Text - normal and functional lookups.
The normal lookup effectively says "give me all the rowids that satisfy my text criteria", whereas the functional lookup says "does row satisfy my text criteria?"

In the case of a functional lookup, there is no need for any special processing.
Functional lookup uses the $K table, and this table is updated immediately the record is changed.
也就是说在functional lookup会用到$K表。

上面查询举到的例子说的都是normal lookup。那什么是functional lookup呢?

2、oracle如何知道当前会话有没有删除或者修改数据?

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/231499/viewspace-63756/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/231499/viewspace-63756/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值