1. 程式人生 > >Oracle模糊查詢之(4.採用全文索引解決模糊查詢,給出具體步驟)採用全文索引解決模糊查詢速度慢的問題[主文]

Oracle模糊查詢之(4.採用全文索引解決模糊查詢,給出具體步驟)採用全文索引解決模糊查詢速度慢的問題[主文]

採用全文索引解決模糊查詢速度慢的問題

上一篇 /下一篇  2009-09-22 20:58:34

眾所周知,使用 like 進行模糊查詢速度極差,包括 like 'AAA%' ,like '%AAA',like '%AAA%',like '%A%A%'以及採用“_”進行單字元匹配的那些模糊查詢。網上有很多文章講到如何提高like查詢,提到 like 'AAA%'能夠使用到索引,而like '%AAA' ,使用建立反向函式的索引來提高查詢效率。但一般情況下,是無法約定客戶端採用哪種like查詢,難道說把所有的這些情況都進行if判斷嗎?

為這個事情腦袋疼了無數次。最近,一客戶“無理”要求對使用者地址模糊查詢速度太慢。在數十萬的使用者記錄下查詢,要求5秒之內必須查詢到記錄。

想破腦袋還是找不到方法。有同事找了本Lucene的書給我看,說是能解決。翻來覆去的看了2,3遍,始終想不出這玩意兒怎麼用。

突然想到oracle也有全文索引一說,以前只是別人提起過這個詞。與網上朋友一聊,說是似乎可以解決,但他忘了怎麼用了。

半夜12點,趕緊爬起來,到google上查資料。還真有兩下子,研究了幾個小時,有所獲。第二天白天沒時間研究,晚上繼續,最終把全文索引搞定,解決了模糊查詢速度慢的問題,在數十萬條使用者資料中, 對使用者地址進行模糊查詢速度在2秒以內就能夠查到。

-------------------------------------------------------------------------

以下是建立全文索引的方法(網上有文章提到使用圖形化介面,我用圖形化介面建立全文索引,建立了一個晚上,第二天起床居然還沒完。但用SQL命令15分鐘左右就搞定):

對cmng_custominfo 表中的address欄位做全文檢索:
1,在oracle9201中需要建立一個分詞的東西:

BEGIN
ctx_ddl.create_preference ('SMS_ADDRESS_LEXER', 'CHINESE_LEXER');
--ctx_ddl.create_preference ('my_lexer', 'chinese_vgram_lexer'); 不用
end;

2,建立全文檢索:

CREATE INDEX INX_CUSTOMINFO_ADDR_DOCS ON cmng_custominfo(address) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('LEXER SMS_ADDRESS_LEXER');

3,查詢時候,使用:

select * from cmng_custominfo where contains (address, '金色新城')>1;

自己測試,發現select * from cmng_custominfo where contains (address, '%金色新城%')>1;才能實現模糊查詢,並且使用了索引,資料庫版本為oracle9.0.1.1.1

4,需要定期進行同步和優化:
同步:根據新增記錄的文字內容更新全文搜尋的索引。

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

優化:根據被刪除記錄清除全文搜尋索引中的垃圾

begin
ctx_ddl.optimize_index('INX_CUSTOMINFO_ADDR_DOCS', 'FAST');
end;

5,採用job做步驟4中的工作:

1)該功能需要利用oracle的JOB功能來完成
因為oracle9I預設不啟用JOB功能,所以首先需要增加ORACLE資料庫例項的JOB配置引數:
job_queue_processes=5
重新啟動oracle資料庫服務和listener服務。

2)同步 和 優化
--同步 sync:
variable jobno number;
BEGIN
DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.sync_index(''INX_CUSTOMINFO_ADDR_DOCS'');', SYSDATE, 'SYSDATE + (1/24/4)');
 commit;
END;

--優化
variable jobno number;
begin
 DBMS_JOB.SUBMIT(:jobno,'ctx_ddl.optimize_index(''INX_CUSTOMINFO_ADDR_DOCS'',''FULL'');', SYSDATE, 'SYSDATE + 1');
 commit;
END;

其中, 第一個job的SYSDATE + (1/24/4)是指每隔15分鐘同步一次,第二個job的SYSDATE + 1是每隔1天做一次全優化。具體的時間間隔,可以根據應用的需要而定

6,索引重建
重建索引會刪除原來的索引,重新生成索引,需要較長的時間。
重建索引語法如下:
ALTER INDEX INX_CUSTOMINFO_ADDR_DOCS REBUILD;

據網上一些用家的體會,oracle重建索引的速度也是比較快的,有一用家這樣描述:

Oracle 的全文檢索建立和維護索引要比ms sql server都要快得多,筆者的65萬記錄的一個表建立索引只需要20分鐘,同步一次只需要1分鐘。
因此,也可以考慮用job的辦法定期重建索引。