Oracle全文索引及定时任务(总结)

Oracle全文索引及定时任务(总结)

  • 全文索引
    • 一.建立索引前提
    • 二.设置分析器
    • 三.创建过滤词组
    • 四.创建全文索引
    • 五.查询索引建立详情
    • 六.测试索引效率
  • 索引定时任务(同步/优化)
    • 一.手动同步与优化
    • 二.定时同步与优化
  • 补充
    • Interval参数值

全文索引

Oracle的全文检索实现逻辑,通过lexer词法分析器,把值的term找出来。相对于使用like,或者instr函数,速度有着明显的优势。但是因为分词,所以会占用的一定的空间。如果空间足够以及对速度有一样的需求,可以考虑全文检索。

一.建立索引前提

  1. 检查和设置数据库角色首先检查数据库中是否有CTXSYS用户CTXAPP角色。oracle11g 默认安装的都有,如果没有这个用户和角色,意味着你的数据库创建时未安装intermedia功能,需要修改数据库安装这项功能。
  2. 默认安装情况下,ctxsys用户是被锁定的,因此要先启用ctxsys的用户;并且要在用户下把ctx_ddl的执行权限赋于要使用全文索引的用户。
    解锁:ALTER ${用户} CTXSYS ACCOUNT UNLOCK;
    赋权:grant execute on ctx_ddl to ${用户}

二.设置分析器

oracle text中的分析器有3种:

1. basic_lexer:
针对英文,只能根据空格和标点来进行拆分。比如“中国深圳”,只能拆分为“中国深圳”一个词,根据“中国”或者“深圳”就搜索不到。
2. chinese_vgram_lexer:
专门的汉语分析器,按字单元进行拆分,比如“中国深圳”,可以拆分为“中”、“中国“、”国深”、“深圳”、“圳”五个词组。这种方式的好处是能够将所有有可能的词组全部保存进索引表,使得数据不会遗漏,但是效率上来说就差强人意了。
3. chinese_lexer:
一种新的汉语分析器,能够认识大部分常用的汉语词汇,较与chinese_vgram_lexer机械式的拆分,能够按常用词汇进行拆分存储。比如“中国深圳”,只会被拆分为“中国”、“深圳”两个词组,但是精确度没有上一个分析器高。
指定分析器代码如下:其中my_lexer是自定义的分析器名

BEGIN
  ctx_ddl.create_preference ('my_lexer', 'chinese_lexer');
END;

三.创建过滤词组

在我们建索引的时候,通常需要对一些常用的词组进行过滤,比如对公司名称进行检索时,肯定不希望输入“有限公司”、“公司”等关键词时,也会有搜索结果。
创建过滤词组:

exec ctx_ddl.create_stoplist('my_stoplist');  

自定义需要过滤的词组内容:

ctx_ddl.add_stopword('my_stoplist','有限公司');  
ctx_ddl.add_stopword('my_stoplist','股份有限公司'); 

意思就是,创建了一个名为“my_stoplist”的过滤词组,“有限公司”、“股份有限公司”这两个词组不会被创建为索引。

四.创建全文索引

对指定列建立全文索引:

create index INX_ATTRIBUTION  on gsmdata(ATTRIBUTION) indextype is 
CTXSYS.CONTEXT parameters('lexer my_lexer stoplist my_stoplist');

注释版:

CREATE INDEX  ${INDEX_NAME} ON ${TABLE_NAME}(${CLOUM_NAME}) indextype
 is ctxsys.context  parameters('lexer ${分析器} stoplist ${过滤词组}');

总结:在gsmdata表中的ATTRIBUTION字段上创建索引,索引类系那个为context类型,该索引用到的分析器为前面定义的my_lexer,该索引用到的过滤词组为前面定义得my_stoplist。

五.查询索引建立详情

1.查询该索引的所有相关信息:

select * from user_indexes where index_name = 'INDEXS_NAME';--//查询的信息更详细
select * from user_ind_columns where index_name = 'INDEXS_NAME';

2.查询表建立了哪些索引:

select index_name from dba_indexes where table_name='TABLE_NAME'

六.测试索引效率

使用全文索引:

select * from gsmdata where contains(ATTRIBUTION,'电信')>0

使用oracle自带操作:

SELECT * FROM gsmdata WHERE INSTR (ATTRIBUTION, '电信') > 0;
SELECT * FROM gsmdata WHERE ATTRIBUTION LIKE '%电信%';


索引定时任务(同步/优化)

一.手动同步与优化

对表的dml操作是不会更新全文索引的,这个也是全文索引的一个特点,索引我们必须手动去维护索引,具体写法如下:

execctx_ddl.sync_index('${索引字段}');--同步索引,将新的数据同步到索引
exec ctx_ddl.optimize_index('${索引字段}','FULL');--优化索引

二.定时同步与优化

1.创建日志记录表–记录同步与优化操作

create table JOBTEST (ID DATE, CONTENT VARCHAR2(200));

2.创建 同步存储过程 (PROC_SYNC_INDEX为该同步的自定义名称)

create or replace procedure PROC_SYNC_INDEX
is
begin
ctx_ddl.sync_index('INDEX_NAME');--//执行同步全文索引
insert into JOBTEST values(SYSDATE, '同步任务于'||SYSDATE||'执行');
end;

3.创建同步优化存储过程, (PROC_SYNC_OPTIMIZE=优化的自定义名称,INDEX_NAME=索引名称)

create or replace procedure PROC_SYNC_OPTIMIZE
is
begin
ctx_ddl.sync_index('INDEX_NAME');
ctx_ddl.optimize_index('INDEX_NAME','FULL');--//执行同步优化索引
insert into JOBTEST values(SYSDATE, '同步优化任务于'||SYSDATE||'执行');
end;

4.查看/删除存储过程

--//查看创建的存储过程
select * from user_procedures;
--//删除存储过程(PROC_SYNC_INDEX=上面的存储过程的名称)
DROP PROCEDURE PROC_SYNC_INDEX

5.创建同步定时任务

DECLARE
       X NUMBER;//定时器的id
BEGIN
   SYS.DBMS_JOB.SUBMIT
   (
    job        => X   --//输出变量,是此任务在任务队列中的编号
   ,what       => 'PROC_SYNC_INDEX;'   --//执行的任务的名称及其输入参数
   ,next_date  => SYSDATE  --//任务执行的时间,一般为当前时间
   ,interval   => 'TRUNC(SYSDATE + 1)'   --//任务执行的时间间隔,这个就是每天午夜12点同步
   );
END;

6.创建优化定时任务

DECLARE
       X NUMBER;
BEGIN
   SYS.DBMS_JOB.SUBMIT
   (
    job        => X  --//输出变量,是此任务在任务队列中的编号
   ,what       => 'PROC_SYNC_OPTIMIZE;'  --//执行的任务的名称及其输入参数
   ,next_date  => SYSDATE  --//任务执行的时间,一般为当前时间
   ,interval   => 'TRUNC(SYSDATE + 1)' --//任务执行的时间间隔,这个就是每天午夜12点同步
   );
END;

7.查看同步与优化的日志/执行job详情

select * from JOBTEST  --//查看同步与优化的操作日志
select * from user_jobs;  --//查看调度任务(同步与优化等多个任务的详情表)
select * from dba_jobs_running;  --//查看正在执行的所有调度任务
select * from dba_jobs;  --//查看执行完的调度任务

8.删除定时器job

BEGIN
  /*23为job的id,此id不是随便填写的,而是执行select * from user_jobs;查询到定时任务名称对应的id*/
  dbms_job.remove(23); 
END;

9.job创建成功却不执行
原因:如果创建存储过程,执行job都没有出问题,那么大概率就是ORACLE默认的定时任务执行范围等于“0”或者设置太小,需要重新进行设置。

 --//查看oracle默认的定时任务执行范围
 select value from v$parameter where name like '%job_queue_processes%' 
 --//修改定时任务执行范围
 alter system set job_queue_processes =1000;


补充

Interval参数值

interval 参数 是一个表示Oracle合法日期表达式的字符串。

1.设置固定的运行时间间隔

每天运行一次 'SYSDATE + 1'
每小时运行一次 'SYSDATE + 1/24'1分钟运行一次 'SYSDATE + 1/24/60'10分钟运行一次 'SYSDATE + 10/(60*24)'30秒运行一次 'SYSDATE + 30/(60*24*60)'
每隔一星期运行一次 'SYSDATE + 7'
不再运行该任务并删除它 'NULL'

2,设置特定的运行时间间隔

Interval => TRUNC(sysdate,’mi’) + 1 / (24*60) //每分钟执行
Interval =>TRUNC(SYSDATE + 1)   //每天午夜12点     
Interval => TRUNC(sysdate) + 1 +2 / (24) //每天的凌晨2点执行  
Interval => TRUNC(SYSDATE + 1) +8*60+30/(24*60) //每天早上8点30分
Interval => NEXT_DAY(TRUNC(SYSDATE ), ''TUESDAY'' ) + 12/24//每星期二中午12点 
Interval => TRUNC(LAST_DAY(SYSDATE ) + 1) //每个月第一天的午夜12点 
Interval => TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q' ) -1/24 //每个季度最后一天的晚上11点 
Interval => TRUNC(LEAST(NEXT_DAY(SYSDATE, ''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) +6×60+10/24×60//每星期六和日早上6点10分 

3.job的运行频率设置

时间 代码
每天 trunc(sysdate+1)
每周 trunc(sysdate+7)
每月 trunc(sysdate+30)
每个星期日 next_day(trunc(sysdate),‘星期日’)
每天6点 trunc(sysdate+1)+6/24)
每半个小时 sysdate+30/(24*60)
每个小时的第15分钟运行 trunc(sysdate,‘hh’)+(60+15)/(24*60))
每天固定时间–比如早上8:10分钟 Trunc(Sysdate+1) + (860+10)/2460

综合整理了大部分关于全文索引相关的知识点,希望对大家有用,如有错误望指正。

你可能感兴趣的:(数据库)