@dbsnake-用合适的函数索引来避免看似无法避免的全表扫描

昨天听了@dbsnake的SQL方法论,感觉比第一次要更有感觉,希望对实际工作能有帮助。

昨天讲到一处利用reverse函数建立索引,避免全表扫描的case,颇有感触,拿出来试一下。

SQL> create table rev (id number, name varchar2(5));
Table created.

SQL> select * from rev;
        ID NAME
---------- -----
         1 abc
         2 bc
         3 c

SQL> create index rev_idx0 on rev(name);
Index created.

SQL> set autot on
SQL> select id, name from rev where name like '%bc';
        ID NAME
---------- -----
         1 abc
         2 bc

Execution Plan
----------------------------------------------------------
Plan hash value: 3205185662

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |    34 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| REV  |     2 |    34 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("NAME" LIKE '%bc')

Note
-----
   - dynamic sampling used for this statement

Statistics
----------------------------------------------------------
          5  recursive calls
          0  db block gets
         16  consistent gets
          0  physical reads
          0  redo size
        633  bytes sent via SQL*Net to client
        492  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed

这里建立了name的B树索引,但由于使用了%bc为条件,所以不会用索引,这里用了全表扫描。

如何能让%bc条件使用索引呢?这里讲到%bc不能用索引的原因是因为索引键值按照索引二进制的顺序排序,%在前就无法精确定位,因此无法使用索引。既然%在后面可以使用索引,那就想办法将%的条件放在后面组织。

SQL> create index rev_idx on rev(reverse(name));
Index created.

SQL> select id, name from rev where reverse(name) like reverse('%bc');
        ID NAME
---------- -----
         2 bc
         1 abc

Execution Plan
----------------------------------------------------------
Plan hash value: 2418054352

---------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |     2 |    34 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| REV     |     2 |    34 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | REV_IDX |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(REVERSE("NAME") LIKE 'cb%')
       filter(REVERSE("NAME") LIKE 'cb%')

Note
-----
   - dynamic sampling used for this statement

Statistics
----------------------------------------------------------
         28  recursive calls
          0  db block gets
         14  consistent gets
          0  physical reads
          0  redo size
        633  bytes sent via SQL*Net to client
        492  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed

这里用了reverse函数,相当于方向匹配字符串bc,这样就将前面的%放到了后面。从执行计划看cost从3变为2。

注:

这里可以看到无论哪次执行,物理读都是0,原因我觉得就是第一次执行过一个select * from rev;,因为数据量比较小,第一次select之后,记录就从data file缓存到buffer cache,即使根据LRU算法,负载不是太大的DB,很快的时间内这些数据还可能在其中,没被age out,所以再次执行SQL时,就可能物理读是0。

总结:

以上的示例就是@dbsnake讲的“用合适的函数索引来避免看似无法避免的全表扫描“。

时间: 2024-07-29 06:05:25

@dbsnake-用合适的函数索引来避免看似无法避免的全表扫描的相关文章

SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析

在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index Scan))呢?是否所有情况都是如此?又该如何优化呢? 下面我们通过一些简单的例子来分析理解这些现象.下面的实验环境为SQL SERVER 2008,如果在不同版本有所区别,欢迎指正.   堆表单索引 首先我们构建我们测试需要实验环境,具体情况如下所示: DROP TABLE TEST    CRE

使用索引快速全扫描(Index FFS)避免全表扫描的若干场景

使用索引快速全扫描(Index FFS)避免全表扫描(FTS) (文档 ID 70135.1) 什么使用使用Index FFS比FTS好? Oracle 8的Concept手册中介绍: 1. 索引必须包含所有查询中参考到的列. 2. Index FFS只能通过CBO(Index hint强制使用CBO)获得. 3. Index FFS使用hint:/*+ INDEX_FFS() */. Index FFS是在7.3中引入的.在Oracle 7中,它要求初始化参数V733_PLANS_ENABLE

有索引却走全表扫描的实验分析

最近在查询某范围的数据时,返回结果仅占整个表数据的0.05%,在相应字段上有对应索引,然而这部分数据并没有走索引, 将根据如下实验证明此种情况的原因 一 构建环境 1建立测试表 有两个字段,主键ID和手机号,手机号上有B树索引 drop table TEST_HIS -- Create table create table TEST_HIS (   id    number,   phone varchar2(32) ) ; -- Add comments to the table commen

ORACLE SQL调优之记录一次trim函数引发的大表全表扫描

                                                                                                                                       

Oracle之函数索引

Oracle之函数索引 在Oracle中,有一类特殊的索引,称为函数索引(Function-Based Indexes,FBI),它基于对表中列进行计算后的结果创建索引.函数索引在不修改应用程序的逻辑基础上提高了查询性能.如果没有函数索引,那么任何在列上执行了函数的查询都不能使用这个列的索引.当在查询中包含该函数时,数据库才会使用该函数索引.函数索引可以是一个B-Tree索引或位图索引. 用于生成索引的函数可以是算术表达式,也可以是一个包含SQL函数.用户定义PL/SQL函数.包函数,或C调用的

[20170402]函数索引standard_hash.txt

[20170402]函数索引standard_hash.txt --//这几天放假,在家里看书<<Apress.Expert.Oracle.Indexing.and.Access.Paths.Maximum.Performance.for.Your.Database.2nd.Edition.148421983X.pdf>> --//这本书比较合适初学者,我以前看过第一版,所以这个版本看的很快. --//里面提到函数standard_hash,可以用来满足一般的查询,做一个记录. 1

在Informix中创建并使用函数索引

随着数据量以惊人速度不断增长,数据库管理系统将继续关注性能问题.本文主要介绍一种名为函数索引(functional index)的性能调优技术.根据数据库使用情况的统计信息创建并使用函数索引,可以显著提升SELECT 查询的性能.通过本文了解如何在IBM Informix Dynamic Server 中创建和使用函数索引并最大限度提升查询性能. 简介 在选择数据库管理系统(DBMS)时,性能是一个关键的考虑因素.在执行SELECT.INSERT.UPDATE 和 DELETE 操作时,很多因素

警惕!自定义函数索引的那些陷阱及避坑术

作者介绍 丁俊,DBAplus社群联合发起人,新炬网络专家团成员,性能优化专家,Oracle ACEA,ITPUB开发版资深版主.十年电信行业从业经验,从事过系统开发与维护.业务架构和数据分析.系统优化等工作.电子工业出版社终身荣誉作者,<剑破冰山-Oracle开发艺术>副主编.   当我们对列使用了函数运算之后,如果此列没有函数索引,那么普通索引是无效的.比如where substr(name,1,3)='abc';如果建立了create INDEX idx_t ON t(NAME);  

[20150513]函数索引与CURSOR_SHARING=FORCE

[20150513]函数索引与CURSOR_SHARING=FORCE.txt --经常awr报表,大量听到的建议是你们的应用没有使用绑定变量.国内的许多项目这个问题更加严重,我敢打赌国内80%甚至更高的比例在 --应用中没有绑定变量(OLTP系统). --如果一个新项目我只要看一下程序使用绑定变量的情况,就知道这个项目是垃圾还是豆腐渣工程.到目前为止我接触的项目仅仅有1个做 --的稍微好一点. --如果不修改代码,一个最简单的方式就是修改参数CURSOR_SHARING = FORCE(补充一