以通配符(%)开始的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, ...
随机推荐
- 重构手法之Replace Temp with Query(以查询取代临时变量)
返回总目录 6.4Replace Temp with Query(以查询取代临时变量) 概要 你的程序以一个临时变量保存某一表达式的运算结果. 将这个表达式提炼到一个独立函数中.将这个临时变量的所有引 ...
- 重构手法之Introduce Explaining Variable(引用解释性变量)
返回总目录 6.5Introduce Explaining Variable(引用解释性变量) 概要 你有一个复杂的表达式. 将该复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表 ...
- java之JVM学习--基本机构
JDK,JRE,JVM关系图 JVM物理结构: jvm内存区详解: 程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字 ...
- 【原创】使用workstation安装Xenserver 6.5+cloudstack 4.10----本地存储模式
1. 背景: 近期由于项目和个人学习得需求,开始接触到Cloudstack,虽然云计算概念在大学刚毕业的时候就已经略有耳闻,但是由于工作原因,也一直没有了解,下班后想自己折腾下cloudstack,便 ...
- OpenTSDB-Querying or Reading Data
Querying or Reading Data OpenTSDB offers a number of means to extract data such as CLI tools, an HTT ...
- Python之文件与目录
file 通常建议使用open()打开文件,file用于类型判断 如果要把数据写到磁盘上,除调用flush()外,还得用sync(),以确保数据从系统缓冲区同步到磁盘.close()总是会调用这两个方 ...
- SAX解析文件
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import ja ...
- replace() 所有单词首字母大写
function ReplaceDemo() { var r,re; var s="The quick brown fox jumpe dover the lazy yellow dog.& ...
- eclipse中Maven工程使用Tomcat7以上插件
Maven中使用tomcat:run命令默认是使用Tomcat6的版本, 现在要用到Tomcat7以上的版本,在eclipse的Maven工程中配置如下 第一步:在项目的pom里面加入如下配置: 官网 ...
- .net 分布式的未来:微服务
一.背景&问题 之前框架是一个基于SOA思想设计的分布式框架.各应用通过服务方式提供使用,服务之间通信是RPC方式调用,具体实现基于.NET的WCF通信平台.框架存在如下2个问题: 1.高并发 ...