以通配符(%)开始的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, ...
随机推荐
- 【转】jQuery代码片段备用
在CSDN看到的,记下备用.原文:http://www.csdn.net/article/2013-07-16/2816238-15-jquery-code-snippets-for-develope ...
- pandas选择数据-【老鱼学pandas】
选择列 根据列名来选择某列的数据 import pandas as pd import numpy as np dates = pd.date_range("2017-01-08" ...
- js 图片转换为base64 (2)
<input type="file" id="testUpload"> <img src="" id="img& ...
- android 加载图片圆角等功能的处理
以Glide为例: Glide.with(getContext()).load(item.getSoftLogo()).transform(this.glideRoundTransform).into ...
- 深入浅出多线程——ReentrantLock (一)
ReentrantLock是一个排它重入锁,与synchronized关键字语意类似,但比其功能更为强大.该类位于java.util.concurrent.locks包下,是Lock接口的实现类.基本 ...
- Java面向对象回顾(1)
世界万物皆对象. 面向对象四大特性:继承.封装.多态.抽象 Java中现有类,再有对象.创建对象(对象实例化)必须先创建类. 将对象的特征对应写成类的属性. 将对象的方法对应携程类的方法. 如何创建对 ...
- MySQL学习——基本命令(1)
MySQL添加新用户.为用户创建数据库.为新用户分配权限 参考博客http://blog.csdn.net/u013216667/article/details/70158452 一.登录MySQL ...
- UWP 调用outlook邮箱反馈
public static async Task FeedbackAsync(string address, string subject, string body) { if (address == ...
- 浏览器Agent大全 (含IE 11, Edge)
Edge mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/51.0.27 ...
- while(true)应用 之 实现自己的消息队列
早些时候,一直有个疑问,就是比如你从前端发一个操作之后,后台为什么能够及时处理你的东西呢?当然了,我说的不是,服务器为什么能够立即接收到你的请求之类高大上的东西.而是,假设你用异步去做一个事情,而后台 ...