视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Oracle实现基于函数的索引
2020-11-09 12:51:42 责编:小采
文档


当一个查询运行很慢。通过检查where子句,发现其中的一列应用了sql lower函数,lower函数阻止使用该列上现有的索引。你想要创建一

使用场景:
当一个查询运行很慢。通过检查where子句,发现其中的一列应用了sql lower函数,lower函数阻止使用该列上现有的索引。你想要创建一个基于函数索引来支持这个查询,如下

SQL> select index_name,column_name from user_ind_columns where table_name='T1';

INDEX_NAME COLUMN_NAME
------------------------- ------------------------------
T1_PK OBJECT_ID

SQL> set autotrace trace explain;
SQL> select * from t1 where lower(object_name)='i_undo1';

执行计划
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 908 | 101K| 436 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T1 | 908 | 101K| 436 (1)| 00:00:01 |
--------------------------------------------------------------------------

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

1 - filter(LOWER("OBJECT_NAME")='i_undo1')
从以上可以看出即使该表中有索引也没有使用。

解决方案
1、创建一个基于函数的索引
2、如果使用Oracle database 11g或更高版本,创建一个索引虚拟列

下面实现基于函数的索引

创建索引可以通过以下方式来估计索引所使用空间以及所需要分配的空间

SQL> set serveroutput on
SQL> var used_bytes number;
SQL> var allo_bytes number;
SQL> exec dbms_space.create_index_cost('create index t1_object_name on t1(lower(object_name))',:used_bytes,:allo_bytes);

PL/SQL procedure successfully completed
used_bytes
---------
2269350
allo_bytes
---------
4194304

SQL>create index idx_lower on t1(lower(object_name)) tablespace index_nocompress;

SQL> select * from t1 where lower(object_name)='i_undo1';

执行计划
----------------------------------------------------------
Plan hash value: 2274688371

-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 908 | 101K| 193 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | 908 | 101K| 193 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_LOWER | 363 | | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

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

2 - access(LOWER("OBJECT_NAME")='i_undo1')

注意:不能直接修改一个创建了基于函数索引的列。需要先删除索引,,然后修改列,最后再重建索引。不然会报ora-30556错误(在要修改的列上已定义函数索引或位图联接索引)

查看基于函数的索引定义dba/all/user_ind_expressions

SQL> select index_name,column_expression from user_ind_expressions;

INDEX_NAME COLUMN_EXPRESSION
------------------------- --------------------------------------------------
IDX_LOWER LOWER("OBJECT_NAME")

接着实现在虚拟列创建一个索引

使用场景

现在正使用一个基于函数的索引,但想要获得更好的性能,想将基于函数的索引替换为一个虚拟列,然后在虚拟列上创建索引(需要11g环境或更高版本)。

SQL>alter table t1 add(lower_object_name generated always as (lower(object_name)) virtual);
SQL>create index idx_lower on t1(lower_object_name) tablespace index_nocompress;

由Oracle索引来理解ArcSDE索引

Oracle索引技术之如何建立最佳索引

Oracle索引列NULL值引发执行计划该表的测试示例

Oracle索引 主键影响查询速度

Oracle索引扫描

本文永久更新链接地址:

下载本文
显示全文
专题