以通配符(%)开始的like字符串,走索引

在对oracle的SQL优化过程中经常会遇到【like‘%abc‘】破坏索引的问题,但是如果真有此类需求,该如何在不破坏索引的基础上进行查询呢。

[sql] view plain copy
[email protected]> select reverse(‘123‘) from dual;  

REVERSE(‘123‘)
--------------------------------
321
1 row selected.  

[email protected]> create table test_like as select object_id,object_name from dba_objects;  

Table created.  

[email protected]> create index test_like__name on test_like(object_name);  

Index created.  

[email protected]> create index test_like__name_reverse on test_like(reverse(object_name));  

Index created.  

[email protected]> analyze table test_like compute statistics for table for all indexes;  

Table analyzed.  

[email protected]> set autotrace trace exp  

-- ‘常量开头的like , 会利用index ,没问题…… ‘  

[email protected]> select * from test_like where object_name like AS%‘;  

Execution Plan  

----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=655 Bytes=15720)
1 0 TABLE ACCESS (BY INDEX ROWID) OF ‘TEST_LIKE‘ (Cost=2 Card=655Bytes=15720)
2 1 INDEX (RANGE SCAN) OF ‘TEST_LIKE__NAME‘ (NON-UNIQUE) (Cost=2 Card=118)
--‘开头和结尾都是 % ,对不起,很难优化‘
[email protected]> select * from test_like where object_name like ‘%%‘;  

Execution Plan  

----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=655 Bytes=15720)
1 0 TABLE ACCESS (FULL) OF ‘TEST_LIKE‘ (Cost=6 Card=655 ytes=15720)  

-- ‘以常量结束,直接写的时候是不能应用index的‘
[email protected]> select * from test_like where object_name like ‘%S‘;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=655 Bytes=15720)  

1 0 TABLE ACCESS (FULL) OF ‘TEST_LIKE‘ (Cost=6 Card=655 Bytes=15720)
--‘以常量结束的,加个reverse 函数,又可以用上index了‘  

[email protected]> select * from test_like where reverse(object_name)like reverse(‘%AS‘);
Execution Plan  

----------------------------------------------------------  

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=655 Bytes=15720)
1 0 TABLE ACCESS (BY INDEX ROWID) OF ‘TEST_LIKE‘ (Cost=2 Card=655 Bytes=15720)  

2 1 INDEX (RANGE SCAN) OF ‘TEST_LIKE__NAME_REVERSE‘ (NON-UNIQUE) (Cost=2 Card=118)  

了解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‘);

问题解决。

时间: 2024-11-07 20:16:50

以通配符(%)开始的like字符串,走索引的相关文章

解决like &#39;%字符串%&#39;时索引不被使用的方法

解决like '%字符串%'时索引不被使用的方法 分步阅读 解决like '%字符串%'时索引不被使用的方法,如果like以通配符开头('%abc')时索引会失效会变成全表扫描的操作. 工具/原料 mysql 方法/步骤 如果like以通配符开头('%abc')时索引会失效会变成全表扫描的操作.那么我们改如何解决这个问题.   现在我们建立一个tbl_user表,并加入如下图的数据.   我们现在在建立索引之前查看sql的执行计划.执行的是全表扫描.   现在我们建立name和age的覆盖索引.

字符串的索引和切片

本文主要介绍:字符串的索引,切片及求字符串的长度 代码: #!/usr/bin/env python# author by lh# -*- coding:utf-8 -*- s='hello'ret=len(s)print retret1=s[0:3]print ret1print s[0]print s[1]print s[2]print s[3]print s[4] 运行结果:

效率优化--并行和强制走索引

SELECT/*+parallel(T 16) parallel(B 16) parallel(D 16)*/ T.POLICY_NO, T.DEPARTMENT_CODE, T.PLAN_CODE,   FROM EPCIS_AUTO_POLICY_BASE_INFO T ,        EPCIS_AUTO_POLICY_VEHICLE_INFO B,       EPCIS_AUTO_A_PRE_MID_RESULT D WHERE T.POLICY_NO = B.POLICY_NO  

强制MySQL查询走索引和强制查询不缓存

有些情况下,表中创建了索引但是EXPLAIN的查看执行计划的时候发现并没有走索引.是因为优化器认为该语句不使用索引效率更好. 当然也可以强制走索引.类似: SELECT uid,uname FROM tab_name force index(ind_id); SELECT SQL_NO_CACHE uid,uname FROM tab_name ; 不走逻辑IO,走物理IO.

[Swift]字符串根据索引获取指定字符,依据ASCII编码实现字符和整数的快速转换

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言. 它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646. 请注意,ASCII是American Standard Code for Information Interchange缩写,而不是ASCⅡ(罗马数字2),有很多人在这个地方产生误解. 在Swift中实现:字符串根据索

sql查询未走索引问题分析之查询数据量过大

前因: 客户咨询,有一个业务sql(代表经常被执行且重要),全表扫描在系统占用资源很高(通过ash报告查询得到信息) 思路: 1.找到sql_text,sql_id 2.查看执行计划 3.查询sql涉及对象的对象数据量,段大小,行数量,where条件列,是否存在索引,列的选择读情况如何 4.总结,优化整改 1.找到sql_text,sql_id 094cmrxrahdy2 SELECT 8~10个列名称(由于设计用户信息,因此部分信息不再详细说明) FROM Prescription WHERE

like模糊查询是否走索引

1.模糊查询,后通配 走索引 ,前通配 走全表 2.where条件用in或or 不会走索引 3.order by 排序时,如果碰到相同的值,则会随机进行排序,排序出来的结果集不是固定的.建议使用id序列进行排序(唯一的值).   原文地址:https://www.cnblogs.com/chenglangpofeng/p/10643387.html

oracle like模糊查询不能走索引?

这里要纠正一个网上很多教程说的模糊匹配不能走索引的说法,因为在看<收获,不止SQL优化>一书,里面举例说到了,并且自己也跟着例子实践了一下,确实like一些特殊情况也是可以走索引的 例子来自<收获,不止SQL优化>一书,实践准备: //建表,注意要非空数据 drop table t purge; create table t as select * from dba_objects where object_id is not null; select * from t; //更新

11 怎么给字符串加索引

11 怎么给字符串加索引 现在,几乎所有的系统都支持邮箱登录,如何在邮箱这样的字段上建立合理的索引? 用户表定义 mysql> create table SUser( ID bigint unsigned primary key, email varchar(64), ... )engine=innodb; 由于要使用邮箱登录,所有业务代码中一定会出现类似这样的语句 mysql> select f1, f2 from SUser where email='xxx'; 在email上创建索引 m