以通配符(%)开始的like字符串,走索引
在对oracle的SQL优化过程中经常会遇到【like'%abc'】破坏索引的问题,但是如果真有此类需求,该如何在不破坏索引的基础上进行查询呢。
[sql] view plain copy
sys@mescp> select reverse('') from dual; REVERSE('')
-------------------------------- row selected. sys@mescp> create table test_like as select object_id,object_name from dba_objects; Table created. sys@mescp> create index test_like__name on test_like(object_name); Index created. sys@mescp> create index test_like__name_reverse on test_like(reverse(object_name)); Index created. sys@mescp> analyze table test_like compute statistics for table for all indexes; Table analyzed. sys@mescp> set autotrace trace exp -- '常量开头的like , 会利用index ,没问题…… ' sys@mescp> select * from test_like where object_name like AS%'; Execution Plan ----------------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost= Card= Bytes=)
TABLE ACCESS (BY INDEX ROWID) OF 'TEST_LIKE' (Cost= Card=655Bytes=)
INDEX (RANGE SCAN) OF 'TEST_LIKE__NAME' (NON-UNIQUE) (Cost= Card=)
--'开头和结尾都是 % ,对不起,很难优化'
sys@mescp> select * from test_like where object_name like '%%'; Execution Plan ----------------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost= Card= Bytes=)
TABLE ACCESS (FULL) OF 'TEST_LIKE' (Cost= Card= ytes=) -- '以常量结束,直接写的时候是不能应用index的'
sys@mescp> select * from test_like where object_name like '%S';
Execution Plan
----------------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE (Cost= Card= Bytes=) TABLE ACCESS (FULL) OF 'TEST_LIKE' (Cost= Card= Bytes=)
--'以常量结束的,加个reverse 函数,又可以用上index了' sys@mescp> select * from test_like where reverse(object_name)like reverse('%AS');
Execution Plan ---------------------------------------------------------- SELECT STATEMENT Optimizer=CHOOSE (Cost= Card= Bytes=)
TABLE ACCESS (BY INDEX ROWID) OF 'TEST_LIKE' (Cost= Card= Bytes=) INDEX (RANGE SCAN) OF 'TEST_LIKE__NAME_REVERSE' (NON-UNIQUE) (Cost= Card=)
了解SQL的同学,都知道,like关键字可以走索引,只要字符串不是以通配符(%)开始。
如果类似 like "%xxx" 的sql,如何走索引呢?基于REVERSE()函数来创建一个函数索引。
1、准备数据:
CREATE TABLE jka AS SELECT ROWNUM id, dbms_random.string('x',10) v FROM dual CONNECT BY LEVEL <= 10000;
2、创建原始索引:
CREATE INDEX jka_normal ON jka (v); BEGIN
dbms_stats.gather_table_stats
(USER
,'JKA'
,estimate_percent=>100
,cascade=>TRUE);
END;
3、以下SQL基于jka_normal索引走范围扫描:
SELECT * FROM jka WHERE v LIKE 'ABC%';
4、但是下面的SQL将走全表扫描(不会使用索引):
SELECT * FROM jka WHERE v LIKE '%ABC';
5、现在,创建一个函数索引(不要与反向索引[REVERSE INDEX]混淆):
CREATE INDEX jka_reverse ON jka(REVERSE(v)); BEGIN
dbms_stats.gather_table_stats
(USER
,'JKA'
,estimate_percent=>100
,cascade=>TRUE);
END;
6、下面的SQL将基于jka_reverse索引走范围扫描:
SELECT * FROM jka WHERE REVERSE(v) LIKE REVERSE('%ABC');
问题解决。
以通配符(%)开始的like字符串,走索引的更多相关文章
- oracle数据库使用hint来让模糊查询走索引
在没有创建数据直方图之前,查询优化器是cbo,可能不会选择代价最低(效率最高)的方式查询. 先创建表 --日语假名表 CREATE TABLE JAPANESE_SOUNDMARK ( ID INTE ...
- 解决like '%字符串%'时索引不被使用的方法
解决like '%字符串%'时索引不被使用的方法 分步阅读 解决like '%字符串%'时索引不被使用的方法,如果like以通配符开头('%abc')时索引会失效会变成全表扫描的操作. 工具/原料 ...
- varchar int 查询 到底什么情况下走索引?
一个字符类型的.一个int类型的,查询的时候到底会不会走索引,其实很多工作了几年的开发人员有时也会晕,下面就用具体事例来测试一下. 1. 准备工作 先准备2张表,以备后续测试使用. 表1:创建表te ...
- 如何根据执行计划,判断Mysql语句是否走索引
如何根据执行计划,判断Mysql语句是否走索引
- 数据类型&字符串得索引及切片
一:数据类型 1):int 1,2,3用于计算 2):bool ture false 用于判断,也可做为if的条件 3):str 用引号引起来的都是str 存储少量数据,进行 ...
- mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?
情况描述:在MySQL的user表中,对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引? 根据查询字段的位置不同来决定,如查询a, a,b a,b, ...
- sql查询未走索引问题分析之查询数据量过大
前因: 客户咨询,有一个业务sql(代表经常被执行且重要),全表扫描在系统占用资源很高(通过ash报告查询得到信息) 思路: 1.找到sql_text,sql_id 2.查看执行计划 3.查询sql涉 ...
- mysql 索引 create_time 加explain关键字是否走索引
SELECT * FROM t_user WHERE email='217@xxg.com'; --1.725 --加email索引之后 0.003 SELECT * FROM t_user WHE ...
- MySQL实现强制查询走索引和强制查询不缓存
0.表结构如下:(包含两个索引) Create Table: CREATE TABLE `user` ( `userID` ) NOT NULL, `userCode` ) DEFAULT NULL, ...
随机推荐
- [转载] ZooKeeper的Java客户端API
转载自 http://www.cnblogs.com/ggjucheng/p/3370359.html http://zookeeper.apache.org/doc/trunk/javaExampl ...
- Spring Boot中采用Mockito来mock所测试的类的依赖(避免加载spring bean,避免启动服务器)
最近试用了一下Mockito,感觉真的挺方便的.举几个应用实例: 1,需要测试的service中注入的有一个dao,而我并不需要去测试这个dao的逻辑,只需要对service进行测试.这个时候怎么办呢 ...
- Javaweb学习(一):tomcat服务器配置与启动
目前所使用的集成开发环境为myeclipse10.7,tomcat版本为apache-tomcat-7.0.82,部分编写地方可能有所不同,但是工具不是最主要的,重要的是掌握的知识. tomcat在m ...
- Cngigure和BUS实现远端配置
1 server依赖 <?xml version="1.0" encoding="UTF-8"?><project xmlns="h ...
- Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法
找到Help Viewer程序的位置(可以使用Everything工具搜索microsoft help找到),发送到桌面快捷方式,打开此快捷方式的属性,在目标的最后添加下面那行字,然后即可通过快捷方式 ...
- [转]the service mysql57 failed the most recent status[/br]mysql57 was not found解决办法
转自:http://forums.mysql.com/read.php?169,622722,622877#msg-622877 安装完mysql5.7.12后想要stop或者restart都会出现以 ...
- 【笔记】web 的回流与重绘及优化
最近看了幕课网 web 前端性能优化的课程,其中说到了浏览器的回流(reflow) 及 重绘(repaint).觉得以后面试或许会被问到所以做一下笔记: 课程从回流及重绘这两个点延伸出了一个知识点就是 ...
- JavaEE中的MVC(四)AOP代理
咱们来吹牛,JDK的动态代理在AOP(Aspect Oriented Programming,面向切面编程)中被称为AOP代理,而AOP是Spring框架中的重要组成部分. 代理模式 但是什么是代理模 ...
- CS窗体程序数据列表分页
以前,觉得winform程序分页很无趣,也没实际意义,直到近期的项目实践中让我认识到原来winform数据列表分页也是非常有必要的,因为由于数据量过大的情况,当窗体在初始加载数据的时候如果不做条件的限 ...
- php获取当前月与上个月月初及月末时间戳的方法
php 获取今日.昨日.上周.本月的起始时间戳和结束时间戳的方法,主要使用到了 php 的时间函数 mktime.下面首先还是直奔主题以示例说明如何使用 mktime 获取今日.昨日.上周.本月的起始 ...