Oracle 模糊查询 优化
模糊查询是数据库查询中经常用到的,一般常用的格式如下:
(1)字段 like '%关键字%' 字段包含"关键字“的记录 即使在目标字段建立索引也不会走索引,速度最慢
(2)字段 like '关键字%' 字段以"关键字"开始的记录 可以使用到在目标字段建立的升序索引
(3)字段 like '%关键字' 字段以"关键字“结束的记录 可以使用到目标字段建立的降序索引
对于无法使用索引的 '%关键字%' 模式,有没有办法优化呢,答案是肯定的,
在ORacle中提供了instr(strSource,strTarget)函数,比使用'%关键字%'的模式效率高很多。
instr函数说明:
INSTR
(源字符串, 目标字符串, 起始位置, 匹配序号)
在Oracle/PLSQL中,instr函数返回要截取的字符串在源字符串中的位置。只检索一次,就是说从字符的开始
到字符的结尾就结束。
语法如下:
instr( string1, string2 [, start_position [, nth_appearance ] ] )
参数分析:
string1
源字符串,要在此字符串中查找。
string2
要在string1中查找的字符串.
start_position
代表string1 的哪个位置开始查找。此参数可选,如果省略默认为1. 字符串索引从1开始。如果此参数为正,从左到右开始检索,如果此参数为负,从右到左检索,返回要查找的字符串在源字符串中的开始索引。
nth_appearance
代表要查找第几次出现的string2. 此参数可选,如果省略,默认为 1.如果为负数系统会报错。
注意:
如果String2在String1中没有找到,instr函数返回0.
示例:
SELECT instr('syranmo','s') FROM dual; -- 返回 1
SELECT instr('syranmo','ra') FROM dual; -- 返回 3
SELECT instr('syran mo','a',1,2) FROM dual; -- 返回 0
对比:
instr(title,'手册')>0 相当于 title like '%手册%'
instr(title,'手册')=1 相当于 title like '手册%'
instr(title,'手册')=0 相当于 title not like '%手册%'
模糊查询优化:
了解了instr函数的用法,优化就变得简单了,例如 %关键字% 等同于 instr(字段,'关键字')>0
实际应用:
t表中将近有1100万数据,很多时候,我们要进行字符串匹配,在SQL语句中,我们通常使用like来达到我们搜索的目标。但经过实际测试发现,like的效率与instr函数差别相当大。下面是一些测试结果:
SQL> set timing on
SQL> select count(*) from t where instr(title,'手册')>0;
COUNT(*)
----------
65881
Elapsed: 00:00:11.04
SQL> select count(*) from t where title like '%手册%';
COUNT(*)
----------
65881
Elapsed: 00:00:31.47
SQL> select count(*) from t where instr(title,'手册')=0;
COUNT(*)
----------
11554580
Elapsed: 00:00:11.31
SQL> select count(*) from t where title not like '%手册%';
COUNT(*)
----------
11554580
另外,我在结另外一个2亿多的表,使用8个并行,使用like查询很久都不出来结果,但使用instr,4分钟即完成查找,性能是相当的好。这些小技巧用好,工作效率提高不少。通过上面的测试说明,ORACLE内建的一些函数,是经过相当程度的优化的。
instr(title,’aaa’)>0 相当于like
instr(title,’aaa’)=0 相当于not like
特殊用法:
select id, name from users where instr('101914, 104703', id) > 0;
它等价于
select id, name from users where id = 101914 or id = 104703;
使用Oracle的instr函数与索引配合提高模糊查询的效率
一般来说,在Oracle数据库中,我们对tb表的name字段进行模糊查询会采用下面两种方式:
1.select * from tb where name like '%XX%';
2.select * from tb where instr(name,'XX')>0;
若是在name字段上没有加索引,两者效率差不多,基本没有区别。
为提高效率,我们在name字段上可以加上非唯一性索引:
create index idx_tb_name on tb(name);
这样,再使用
select * from tb where instr(name,'XX')>0;
这样的语句查询,效率可以提高不少,表数据量越大时两者差别越大。但也要顾及到name字段加上索引后DML语句会使索引数据重新排序的影响。
另一种未知的方案:
有人说了用全文索引,我看了,步骤挺麻烦,但是是个不错的方法,留着备用:
http://sandish.itpub.net/post/4899/464369
对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;
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的办法定期重建索引。
Oracle 模糊查询 优化的更多相关文章
- Oracle 模糊查询方法
在这个信息量剧增的时代,怎样帮助用户从海量数据中检索到想要的数据.模糊查询是不可缺少的. 那么在Oracle中模糊查询是怎样实现的呢? 一.我们能够在where子句中使用likeke ...
- Oracle模糊查询CONCAT参数个数无效
在使用MyBatis操作Oracle数据库的时候,写模糊查询突然发现原本在MySql中正确的代码,在Oracle中报错,参数个数无效 <if test="empId!=null and ...
- oracle模糊查询mysql的区别
https://blog.csdn.net/weixin_38673554/article/details/86503982#_1 oracle与使用mysql的区别 https://www.cnbl ...
- oracle模糊查询效率提高
1.使用两边加‘%’号的查询,oracle是不通过索引的,所以查询效率很低. 例如:select count(*) from lui_user_base t where t.user_name lik ...
- oracle模糊查询效率可这样提高
1.使用两边加'%'号的查询,oracle是不通过索引的,所以查询效率很低. 例如:select count(*) from lui_user_base t where t.user_name lik ...
- oracle 模糊查询中的转义字符用法
drop view aaa; create view aaa as select '_BCDE' A FROM DUAL UNION ALL SELECT 'ABCDE' FROM DUAL UNIO ...
- Oracle模糊查询
通配符 % 匹配零个或更多的任意字符 _ 匹配一个任意字符 [ ] 匹配指定范围中的一个字符([a-z],[0-9]) [^ ] 不属于指定范围,不包含其中的字符 escape转义 --查询 ...
- oracle模糊查询提高效率的方法
转载:https://blog.csdn.net/weixiaohuai/article/details/83513957 https://blog.csdn.net/chihen/article/d ...
- LinqToEntity模糊查询的方法选择
LinqToEntity针对oracle模糊查询 方法:Contains() 转换出来的sql是 like 关键字 方法:IndexOf() 转换出来的sql是 instr() 函数 lik ...
随机推荐
- RedHat操作指令第4篇
top(查看动态进程运行情况) top 是一个更加有用的命令,可以监视系统中不同的进程所使用的资源.它提供实时的系统状态信息. 显示进程的数据包括 PID.进程属主.优先级.%CPU.%memory等 ...
- CTFHub Web题学习笔记(Web前置技能+信息泄露题解writeup)
今天CTFHub正式上线了,https://www.ctfhub.com/#/index,之前有看到这个平台,不过没在上面做题,技能树还是很新颖的,不足的是有的方向的题目还没有题目,CTF比赛时间显示 ...
- MySQL技术内幕InnoDB存储引擎(六)——锁
什么是数据库的锁? 锁是数据库系统区别于文件系统的一个关键特性.锁机制用于管理对共享资源的并发访问.让数据库事务满足隔离性的要求. InnoDB 中锁的作用 不仅用于对数据进行并发访问,还还包括了缓冲 ...
- rocketMq指定broker ip地址,适合解决云主机部署问题
在工作中遇到了一个这个问题,就是我们rocketmq是部署在云主机上的 但是我们的开发同事在自己的电脑连接rocketmq链接不上 报错显示Caused by: org.apache.rocket ...
- 调用windows系统下的cmd命令窗口处理文件
从后缀名为grib2的文件中查询相关的信息,并将查出来的信息保存起来. 主要是学习java中调用windows下的cmd平台,并进行执行相关的命令. package com.wis.wgrib2; i ...
- Javascript的解码/编码api
1.fromCharCode() 接受一个指定的 Unicode 值,然后返回一个字符串. 语法:String.fromCharCode(numX,numX,...,numX) 详细了解:http:/ ...
- Android 11 源码下载+编译教程
下载AOSP源码 这里我使用的是外国语大学的镜像执行的下载,Mac系统的话,一定要在区分大小姐的磁盘下执行 repo init -u https://mirrors.bfsu.edu.cn/git/A ...
- js--数组的map()方法的使用
javaScript中Array.map()的用法 前言 作为一个刚刚踏入前端世界的小白,工作中看到身边同事大佬写的代码就像古诗一样简介整齐,而我的代码如同一堆散沙,看上去毫无段落感,而且简单的功能需 ...
- AWT08-绘图
1.组件绘图原理 Java GUI能展示出不同对话框.窗口等等组件外观的本质其实就是绘图. 在AWT中,真正提供绘图功能的是Graphics对象,在Component中提供了三个方法来完成组件图形的绘 ...
- C++ 中使用 PRId64
同一份代码,Ubuntu 14.04.1 编译没有问题,centos 7 上编译提示错误: error: expected ')' before 'PRId64' 这里两个地址说得很清楚了: http ...