oracle全文索引之如何實現查詢

space6212發表於2019-05-06


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

實驗一:直接查詢
> @begin_trace
> select * from t_domain where contains(doc,'shenzhen') >0;

5 this is shenzhen
> @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取出使用者需要的資料。
---------------------------------------------------------------

實驗二、先刪除(或者更新),再查詢
> delete from t_domain where rownum=1;

已刪除 1 行。

> @begin_trace
> select * from t_domain where contains(doc,'shenzhen') >0;
> @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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章