关于like的优化思考
来源:互联网 发布:武汉矩阵互动科技抄袭 编辑:程序博客网 时间:2024/05/18 22:45
原贴地址:http://www.itpub.net/forum.php?mod=viewthread&tid=1702729
在项目中使用oracle数据库,有着两个既是难点也是重点的两条要求,就是数据的准确性以及数据库的性能优化。所以在保证数据一致准确的前提下对database的优化就成为了oracle数据库的一个永恒的主题。
资深的Oracle数据库DBA通常会要求提出性能问题的人对数据库做一个statspack,贴出数据库配置,还有的DBA要求抓出执行最慢的语句的执行计划来进行sql分析。这些都是常用的优化手段。但是根据这些手段只能分析出哪里出现了问题,或者哪条sql出现性能故障,却依然手足无措,其实Oracle SQL 调整是 Oracle 性能调优中最重要的领域之一,只要通过一些简单的 SQL 调优规则就可以大幅度地提升 SQL 语句的性能,这是一点都不奇怪的。对于存在like关键字通配符的模糊查寻的sql 语句往往令developer感到头疼,也许一条简单的sql模糊查询在千万行级别的表中就会执行的很慢,大大的影响了系统的性能,下面针对like的sql语句优化有几点小的建议。
例如:select * from employee where last_name like '%c%;
这样的查询语句在执行的过程中很慢,但是业务中需要有模糊查询的要求,又不得不用like
1. 分析业务需求是否前后都必须是模糊查询如果可以改写成通配符在后面,原因是%XXX%这样的字段使用不到该列的索引,根据CBO规则很可能走的是FULL ACCESS TABLE,而XXX%这样的字段却可以走索引,会加快执行速度。如:select * from employee where last_name like 'c%'
2. 如果业务需求不能前置确定的变量XXX,却可以写成%XXX,虽然这样依然不能够走索引,但是可以通过翻转函数索引来达到优化的目的。如:select * from employee where reverse(last_name) like reverse('%c'); 当然,在这里值得注意的是这个反转索引不是真正意义上的反转索引,只不过是一个反转函数的使用,真正意义上的反转索引是主要防止热块的出现而将索引数据防止在不同的索引数据块中,也就是在索引中使本来连续的值不连续的分布,可以说在频繁的插入的情况下可以减小数据块竞争,但缺点也十分明显,就是在范围 scan的时候就用不上了。
3. 如果业务中必须使用类似%XXX%类似的sql查询,也有几个方案可供选择。
(1)可以采用hint的强制索引,但是优化成功率比较低,根据CBO的优化器计算出的方式可能更加符合性能,但是也不失一种方法所以总结在这里。如:Select /*+INDEX (employee pk_last_name)*/ * from employee where last_name like 'c%' ;
(2)可以采用instr或其他取得XXX字符或者字符位置的函数来代替like的使用达到同样的业务需求。如:select count(*) from employee where instr (last_name,'c') > 0;
(3)如果该表需要被多次访问而且不经常对该表进行添加删改等DML语句操作可以建立物化视图增加查询速度。
(4)如果该表有明显可以分区的字段,比如日期,年份,账期等有关时间的字段,可以建立分区表,考虑从表结构的更改入手调整性能,这种优化多见于数据仓库。
(5)利用并行sql技术,充分利用多核CPU性能来完成sql的查询。如:SELECT /*+PARALLEL(employee,2)*/ * FROM employee WHERE last_name LIKE '%c%' ;
(6)可以采用全文索引技术来实现该字段的全文索引,但是数据精确度可能会有所损失。
(7)最后一个不是方法的方法就是把该字段数据使用其他的技术来实现,而不是依赖于oracle数据库,如果数据比较多的话可以使用基于java的lucene全文搜索引擎技术来实现,但对于架构来讲会增加很大的困难以及增加结构的复杂性,强烈建议不适用这种方法。
原贴地址:http://woodbow.net/91.html
oracle中like优化的一种方法
在oracle中对于like操作时,如果是前后都是模糊查询的时候(类似于col01 like ‘%xxx%’)是没有办法用到索引的,这里提供一种对于这种情况的优化思路,主要的思路是把大表变小,把查询的实体表变窄,把需要的数据放到索引里.
常规的写法:
SQL>
create
index
t01_01
on
t01(object_name);
Index
created.
SQL>
set
autot trace
SQL>
select
*
from
t01
where
object_name
like
'%EMP%'
;
176
rows
selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3295674804
--------------------------------------------------------------------------
| Id | Operation |
Name
|
Rows
| Bytes | Cost (%CPU)|
Time
|
--------------------------------------------------------------------------
| 0 |
SELECT
STATEMENT | | 7091 | 775K| 522 (1)| 00:00:07 |
|* 1 |
TABLE
ACCESS
FULL
| T01 | 7091 | 775K| 522 (1)| 00:00:07 |
--------------------------------------------------------------------------
Predicate Information (identified
by
operation id):
---------------------------------------------------
1 - filter(
"OBJECT_NAME"
LIKE
'%EMP%'
)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2335 consistent gets
0 physical reads
0 redo
size
14552 bytes sent via SQL*Net
to
client
608 bytes received via SQL*Net
from
client
13 SQL*Net roundtrips
to
/
from
client
0 sorts (memory)
0 sorts (disk)
176
rows
processed
优化后的写法:
SQL>
select
/*+ use_nl(t01 v01) */
*
2
from
t01, (
select
rowid
from
t01
where
object_name
like
'%EMP%'
) v01
3
where
t01.rowid = v01.rowid;
176
rows
selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 73453348
--------------------------------------------------------------------------------------
| Id | Operation |
Name
|
Rows
| Bytes | Cost (%CPU)|
Time
|
--------------------------------------------------------------------------------------
| 0 |
SELECT
STATEMENT | | 7091 | 1017K| 7241 (1)| 00:01:27 |
| 1 | NESTED LOOPS | | 7091 | 1017K| 7241 (1)| 00:01:27 |
|* 2 |
INDEX
FAST
FULL
SCAN | T01_01 | 7091 | 242K| 147 (2)| 00:00:02 |
| 3 |
TABLE
ACCESS
BY
USER
ROWID| T01 | 1 | 112 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified
by
operation id):
---------------------------------------------------
2 - filter(
"OBJECT_NAME"
LIKE
'%EMP%'
)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
857 consistent gets
0 physical reads
0 redo
size
18049 bytes sent via SQL*Net
to
client
608 bytes received via SQL*Net
from
client
13 SQL*Net roundtrips
to
/
from
client
0 sorts (memory)
0 sorts (disk)
176
rows
processed
针对于上面的例子,IO从2335降到857,用这种方法在表越宽返回记录越少时效果越好.
- 关于like的优化思考
- 关于 mysql 中 find_in_set 与 like 查询的一些思考
- 关于性能优化的思考
- oracle:关于优化SQL的另类思考
- 关于快速排序的一些优化思考
- 性能 关于性能优化的思考
- 关于思考的思考
- 关于思考的思考
- 简单说两句Like的优化
- oracle中like的优化
- 简单说两句 Like 的优化
- oracle中like的优化
- Like SQL语句的优化
- 关于服务性能优化思考
- 关于Mysql模糊查询的优化-全文检索和Like的使用
- 关于Mysql模糊查询的优化-全文检索和Like的使用
- 关于网络编程中字节序转换优化的思考
- 关于mongodb索引优化的实现与思考
- Android onTouchEvent, onClick及onLongClick的调用机制
- Struts2 result中type的参数说明
- Eclipse 中配置android sdk 提示版本过旧的解决方法
- 5.windbg script-禁用IsDebuggerPresent(调试 kernel32!SetUnhandledExceptionFilter)
- hive的插入操作
- 关于like的优化思考
- android 项目导入错误解决方法收集
- Warning: Cannot modify header information - headers already sent by (output started at...
- protobuf初探
- __extension__ typedef int __ssize_t;是什么意思
- vs2005无法打开工程
- dll的概念、dll导出类(转)
- 【框架-MFC】CMFCMenuBar 菜单按钮的图标添加
- 算法:将table标识的树形结构文本数据快速导入Mysql邻接表