`
pouyang
  • 浏览: 326794 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

数据库 索引 Oracle 10g SQL性能优化-使用函数索引来解决普通索引不发生作用的问题

阅读更多
转自: http://www.iteye.com/articles/2516
正如Oracle 10g SQL性能优化-使用索引提高数据库select语句的性能的例子一样,对于所测试的app_user表,3百万条记录,对于select * from scott.app_user where abs(user_id) = 100000;这条sql,直接在user_id上建索引对这条SQL的访问是没有时间上的改进的,因为在这样的情况下,本质上B树上存的是user_id的值,而不是abs(user_id)的值,所以Oracle采取了全表扫描的方式来访问数据库。

解决这样问题的方法就是在app_user表上建一个abs(user_id)的函数索引,相当于多了一个虚拟列abs(user_id),然后在这个虚拟列上建索引;可以看到执行计划相差较大,从统计信息分析,IO操作少了很多。



1. 概要
昨天在Oracle 10g SQL性能优化-使用索引提高数据库select语句的性能说明了索引对select语句的巨大性能提高,今天,来看一种情况,就是在where语句中,在索引列上有函数操作时,普通的索引并不会发生作用,需要使用函数索引来影响执行计划;

2. 测试基本环境:
* 硬件:T60笔记本,T2500的CPU,2G内存

* 操作系统:Windows xp

* Oracle版本:Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Production

* 主要的SQL测试在一个app_user表上进行,表格有3,000,000条数据;

* 为消除缓存等各方面的影响,每次要select之前都重启Oracle服务,保证缓存是空的;

3. 测试表格定义和记录数
下面是app_user的定义和记录数,3百万记录数已经具有一定的代表性;

注意:看到红色部分,这里user_id上已经有主键;

hetaoblog@ORCL>SELECT DBMS_METADATA.GET_DDL(‘TABLE’,'APP_USER’,'SCOTT’) FROM DUAL;


DBMS_METADATA.GET_DDL(‘TABLE’,'APP_USER’,'SCOTT’)

——————————————————————————–


CREATE TABLE “SCOTT”.”APP_USER”

( “USER_ID” NUMBER(*,0),

“USER_NAME” VARCHAR2(20),

“GENDER” CHAR(1),

“EMAIL” VARCHAR2(30),

CONSTRAINT “UNIQUE_EMAIL” UNIQUE (“EMAIL”)

USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255

TABLESPACE “USERS”  ENABLE,

CONSTRAINT “UNIQUE_NAME” UNIQUE (“USER_NAME”)

USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255

TABLESPACE “USERS”  ENABLE,

CONSTRAINT “APP_USER_PK” PRIMARY KEY (“USER_ID”)

USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS

TABLESPACE “USERS”  ENABLE

) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

TABLESPACE “USERS” ENABLE ROW MOVEMENT


hetaoblog@ORCL>select count(*) from scott.app_user;


COUNT(*)

———-

3000017

4. 测试SQL和过程
4.1测试SQL为:select * from scott.app_user where abs(user_id) = 100000

4.2 测试用例1【无函数索引】
这时,为避免缓存影响,重启数据库,然后执行下面的查询:

hetaoblog@ORCL>select * from scott.app_user where abs(user_id) = 100000;


USER_ID USER_NAME                                GENDER EMAIL

———- —————————————- —— ————————————————————

100000 user100000                               M      user100000@qq.com


已用时间:  00: 00: 09.36


执行计划

———————————————————-

Plan hash value: 2096499096


——————————————————————————

| Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |

——————————————————————————

|   0 | SELECT STATEMENT  |          |   197 |  8865 |  4039   (4)| 00:00:49 |

|*  1 |  TABLE ACCESS FULL| APP_USER |   197 |  8865 |  4039   (4)| 00:00:49 |

——————————————————————————


Predicate Information (identified by operation id):

—————————————————


1 – filter(ABS(“USER_ID”)=100000)


Note

—–

– dynamic sampling used for this statement



统计信息

———————————————————-

432  recursive calls

0  db block gets

18021  consistent gets

17879  physical reads

0  redo size

613  bytes sent via SQL*Net to client

385  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

5  sorts (memory)

0  sorts (disk)

1  rows processed

4.3测试用例2【有函数索引】
下面添加在user_id上的函数索引,对于user_id的abs函数建索引

hetaoblog@ORCL>create index app_user_abs_id on app_user(abs(user_id));


索引已创建。


已用时间:  00: 00: 44.20


添加索引后,重启数据库,再次做查询:

hetaoblog@ORCL>select * from scott.app_user where abs(user_id) = 100000;


USER_ID USER_NAME                                GENDER EMAIL

———- —————————————- —— ————————————————————

100000 user100000                               M      user100000@qq.com


已用时间:  00: 00: 00.96


执行计划

———————————————————-

Plan hash value: 319304378


———————————————————————————————–

| Id  | Operation                   | Name            | Rows  | Bytes | Cost (%CPU)| Time     |

———————————————————————————————–

|   0 | SELECT STATEMENT            |                 |     1 |    45 |    76   (2)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| APP_USER        |     1 |    45 |    76   (2)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | APP_USER_ABS_ID |  9927 |       |     3   (0)| 00:00:01 |

———————————————————————————————–


Predicate Information (identified by operation id):

—————————————————


2 – access(ABS(“USER_ID”)=100000)


Note

—–

– dynamic sampling used for this statement



统计信息

———————————————————-

561  recursive calls

0  db block gets

172  consistent gets

377  physical reads

116  redo size

613  bytes sent via SQL*Net to client

385  bytes received via SQL*Net from client

2  SQL*Net roundtrips to/from client

6  sorts (memory)

0  sorts (disk)

1  rows processed

5. 结论分析:
正如Oracle 10g SQL性能优化-使用索引提高数据库select语句的性能的例子一样,对于所测试的app_user表,3百万条记录,对于select * from scott.app_user where abs(user_id) = 100000;这条sql,直接在user_id上建索引对这条SQL的访问是没有时间上的改进的,因为在这样的情况下,本质上B树上存的是user_id的值,而不是abs(user_id)的值,所以Oracle采取了全表扫描的方式来访问数据库。

解决这样问题的方法就是在app_user表上建一个abs(user_id)的函数索引,相当于多了一个虚拟列abs(user_id),然后在这个虚拟列上建索引;可以看到执行计划相差较大,从统计信息分析,IO操作少了很多。


结果对照表:

SQL运行时间  执行计划主要步骤 一致读 物理读
有函数索引 0. 96秒  INDEX RANGE SCAN  172 377 
无函数索引 09.36秒  TABLE ACCESS FULL 18021 17879



这里以abs函数做例子,其他函数也是一样的情况,比如upper(),lower(),instr(),length(),substr(),instr(),to_date(),trunc(),to_char()等,当在相关列上有函数调用后,普通的索引并不会发生作用,需要使用函数索引来改变查询计划,提高SQL性能
分享到:
评论

相关推荐

    Oracle 10g数据库管理、应用与开发标准教程

    主要内容包括:Oracle关系数据库,Oracle数据库体系结构,SQL基本查询,修改SQL数据与SQL*Plus命令,PL/SQL编程基础,用户、模式和表,高级查询,过程、函数和程序包,表类型,索引,视图、序列和同义词,触发器,...

    oracle性能优化技巧

    ### Oracle性能优化技巧详解 ...综上所述,Oracle性能优化涉及多个方面,包括但不限于优化器的选择、表访问方式、SQL语句的编写和执行等。通过对这些方面的深入了解和合理运用,可以显著提升Oracle数据库的查询性能。

    oracle优化------缓存对象与数据

    在Oracle数据库优化领域,缓存机制是一项关键的技术手段,旨在通过将频繁访问的数据和对象保留在内存中来提高系统的响应速度和整体性能。本篇文章将深入探讨Oracle数据库中的缓存机制,包括缓存数据和缓存数据库对象...

    ORACLE数据库及SQL语言考试题一含答案.pdf

    本文档是关于ORACLE数据库及SQL语言考试题,涵盖了名词解释、ORACLE数据库知识问答和SQL语句编写三部分,旨在考察新同事ORACLE数据库知识和SQL语言掌握情况。 名词解释 1. 数据库:按照数据结构来组织、存储和管理...

    优化数据库的思想及SQL语句优化的原则

    数据库优化不仅涉及硬件配置、系统架构设计,更聚焦于SQL查询的优化,以提高数据检索速度和整体系统性能。本文将深入探讨优化数据库的思想以及SQL语句优化的原则。 一、优化数据库的思想 1. 数据库设计:良好的...

    精通Oracle.10g.Pl.SQL编程.pdf

    本书《精通Oracle.10g.PL/SQL编程》应旨在帮助读者深入理解和掌握在Oracle 10g环境中使用PL/SQL进行高效编程的方法和技巧。 PL/SQL由以下几个核心部分组成: 1. **声明部分**:在这里,你可以声明变量、常量、游标...

    实验授课计划-Oracle数据库教程(第2版)-赵明渊-清华大学出版社.docx

    - **使用视图**:视图可以像普通表一样被查询,但不能直接修改其中的数据。 ### 9. 索引 - **索引的作用**:提高数据检索速度,类似于书的目录。 - **创建索引**:使用CREATE INDEX语句创建索引。 - **索引类型**...

    Oracle实验二-SQL语句综合应用

    在本实验中,我们主要探讨了Oracle数据库中的SQL语句应用,涉及到了表、视图、索引以及序列等核心概念。以下是对这些知识点的详细解释: 1. **创建表**: - 使用`CREATE TABLE`语句创建了一个名为`person`的表,...

    ORACLE数据库及SQL语言考试题一(含答案).docx

    以上知识点涵盖了ORACLE数据库的基本概念、数据备份与恢复、常用SQL函数、数据表的连接方式以及SQL语句的编写等方面的内容。希望这些知识点能够帮助读者更好地理解和掌握ORACLE数据库及SQL语言的相关知识。

    数据库开发 Oracle数据库 SQL开发教程 第15章 视图(共23页).pdf

    Oracle数据库是世界上最广泛使用的数据库管理系统之一,SQL(Structured Query Language)是访问和操作数据库的标准语言。在本章中,我们将深入探讨SQL开发中的一个重要概念——视图,它是Oracle数据库中的一个重要...

    Oracle自学(学习)材料 (共18章 偏理论一点)

    12 管理索引 目标 12-2 索引的分类 12-3 B 树索引 12-4 位图索引 12-6 B 树索引和位图索引的比较 12-7 创建普通 B 树索引 12-8 创建索引:指导 12-10 创建位图索引 12-11 修改索引的储存参数 12-12 分配和回收索引...

    sql优化,大数据量如何解决.docx

    SQL优化是数据库性能优化的关键技术之一,本文将详细介绍SQL优化的各种技术和方法。 索引 索引是SQL优化的基础技术之一,索引可以加速查询速度、提高数据检索效率。常见的索引类型有: 1. 普通索引(Normal Index...

    学生成绩管理系统Oracle全部SQL语句.txt

    选定某一主题,运用oracle数据库,以及相关技术方法设计和开发一个信息管理的数据库系统,实现数据库的开发应用以及日常管理维护等基本功能。 具体要求如下: (1)选定某一主题,创建一个oracle数据库,对其进行...

    sql面试题\oracle面试题目

    Oracle 10g的新特性 - **Automatic Storage Management (ASM)**:自动存储管理。 - **Data Guard Broker**:简化Data Guard管理。 - **Database Resource Manager**:资源管理。 - **Database Replay**:性能诊断...

    Oracle数据库面试题.pdf

    ### Oracle数据库面试题知识点解析 #### 一、基础知识(1-20) 1. **Oracle数据库的主要特点**: - **高性能与可扩展性**:支持大量并发用户和大规模数据处理。 - **高可用性**:具备强大的容错能力和故障恢复...

    oracle 视图、索引(自用)

    视图和索引是Oracle数据库中两个非常关键的概念,它们对于优化查询性能、管理数据以及提高数据安全性都至关重要。以下是对这两个概念的详细解释: 一、Oracle视图 1. 定义:视图是从一个或多个表中创建的虚拟表,它...

Global site tag (gtag.js) - Google Analytics