热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

Oracle索引基本原理

Oracle提供了两种方式:从表中读取所有行(即全表扫描),或者通过ROWID一次读取一行。如果只访问大数据量表中的5%的行,并且使用索

Oracle提供了两种方式:从表中读取所有行(即全表扫描),或者通过ROWID一次读取一行。如果只访问大数据量表中的5%的行,并且使用索

一.索引基本概念
Oracle提供了两种方式:从表中读取所有行(即全表扫描),或者通过ROWID一次读取一行。

如果只访问大数据量表中的5%的行,并且使用索引标识需要读取的数据块,这样话费的I/O较少.索引对性能改进的程度:1.取决于数据的选择性 2.数据在表的数据块中的分布方式

当数据分散在表的多个数据块中时,最好是不使用索引,而是选择全表扫描。执行全表扫描时,oracle使用多块读取以快速扫描表,基于索引的读是单块读。因此在使用索引时的目标是减少完成查询所需的单块读的数量。

增强索引会降低insert语句的性能(因为需要同时对表和索引进行更新).大量行的delete操作将会由于表中存在索引而变慢

在表上加一个索引都会使该表上insert操作的执行时间变成原来的三倍,再加一个索引就会再慢一倍。
视图:
DBA_INDEXS
USER_INDEXS
ALL_INDEXS
显示表的索引

USER_IND_COLUMNS
DBA_IND_COLUMNS
ALL_IND_COLUMNS
显示所有被索引的列

二.不可视索引
每插入一条记录时,就会更新所有索引.oracle允许关闭索引(使其不可见),但是索引上的维护工作还会继续。
alter index idx1 invisible
alter index idx2 visible
create index .. invisible

create index dept_inv_idx on dept_rich(deptno) invisible;
select count(*) from dept_rich where deptno=30;(索引不可见)

在执行计划里是看不到使用索引了
可以使用强制索引使用,通过USE_INVISIBLE_INDEXS提示,或者把初始化参数OPTIMIZER_USE_INVISIBLE_INDEXS设置成true。

select /*+ USE_INVISIBLE_INDEXS */ count(*) from dept_rich where deptno = 30;(通过提示强制使用)
执行计划可以看到使用索引了

在不将其变成不可见的前提下,也可以使用NO_INDEX提示来关闭一个索引.
select /*+ no_index(dept_rich dept_rich_inv_idx) */ count(*) from dept_rich where deptno = 30;(强制不使用带提示的索引)

会发现执行计划走的全表扫描

可以随时将这个索引设成不可见
alter index dept_rich_inv_idx invisible;

三.组合索引
当某个索引包含多个列时,我们称这个索引为"组合索引" 或 "复合索引".

引入的索引跳跃式扫描增加了优化器在使用组合索引时的选择,所以在选择索引中的列顺序时应该谨慎。
索引的第一列应该是最有可能在where子句中使用的列,并且也是索引中最具选择性的列。

create index emp_id1 on emp(empno,ename,deptno);

跳跃式扫描select job,empno from emp where ename='RICH'; 即使where子句中没有指定empno值,优化器也可能会选择使用该索引.也可能使用索引快速扫描或全表扫描。

如果在where子句中使用索引的第三列,也会产生相同的情况。
优化器可能选择索引跳跃式扫描,索引快速扫描或全表扫描。

最常见的索引扫描方式是唯一扫描和范围扫描。在唯一扫描中,数据库知道索引包含每一个值都是唯一的。在范围扫描中,数据库将根据查询条件从索引中返回多个符合条件的值。上面的都是范围扫描
使用create unique index命令可以创建唯一索引.

在创建主键约束或唯一性约束时,oracle将基于指定的列自动创建唯一索引(除非使用disable子句创建约束)。如果创建多列的主键,oracle将创建组合索引,其中的列的排列顺序和创建主键时指定的列的顺序一致。

四.索引抑制
在SQL中有很多陷阱会使一些索引无法使用
1.使用不等于运算符(<> , !=)
索引只能查找表中已存在的数据,每当在where子句中使用不等于运算符时,其中被用到的列上的索引都将无法使用。
例如:select cust_id,cust_name from customers where cust_rating <> 'aa';
oracle在分析表的同时收集表中数据分布的相关统计信息。通过这种方法,基于成本的优化器就可以决定在where子句中对一些值使用索引,而对其他的值不使用.
可以通过create index 命令的compute statistic子句,在创建索引的同时分析它们。

2.使用IS NULL或IS NOT NULL
当在where子句中使用IS NULL或IS NOT NULL的时候,因为NULL值并没有被定义(oracle不会在B树索引中对NULL值索引).所以索引的使用会被抑制。数据库中没有值等于NULL;甚至NULL也不等于NULL.
如果被索引的列在某些行中存在NULL值,在索引中就不会有相应的条目(除非使用位图索引,这是位图索引对于NULL搜索通常很快的原因)。
例如:select empno,deptno from emp where sal is null;
即使sal列上有索引,也会进行全表扫描

只有在表中每一行值都非NULL或是使用alter table命令的default子句时,才可以为列设置NOT NULL属性.
alter table emp modify (sal not null);

create table p(id int,nameid number(4) default 10);
insert into p values(1,NULL);
insert into p values(2,20);
显示:
ID NAMEID
1
2 20
创建表时对列指定NOT NULL或default 可以帮助避免出现的性能问题.

3.使用LIKE
条件中有LIKE关键字会使用索引。
通常有两种写法 LIKE '%some%' 或LIKE 'some%'
当%在前面的时候,索引不会被使用,但是当值在%前面时候,oracle可以使用索引

4.使用函数
除非使用基于函数的索引,否则在SQL语句的where子句中对存在的索引的列使用函数时,优化器会忽略索引.一般常见的索引如:TRUNC,SUBSTR,TO_DATE,TO_CHAR和INSTR等。
例如下面的就会使用全表扫描
select empno,ename,deptno from emp where trunc(hiredate)='01-MAY-01';
改成下面的就可以了
select empno,ename,deptno from emp where hiredate > '01-MAY-01' and hiredate <(TO_DATE('01-MAY-01') + 0.99999);
通过改变所比较的列上的值,而不用改变列本身,就可以启用索引,这样可避免全表扫描.

5.比较不匹配的数据类型
一种很难解决的性能问题是比较不匹配的数据类型。oracle不但不会对那些不兼容的数据类型报错,反而会做隐式数据转换。例如:oracle可以隐式得转换varchar2类型的列中的数据去匹配数值类型数据。
如果account_number列是varchar2数据类型,下面将进行全表扫描
select bank_name,,address,city,state,zip from banks where account_number=99999;
oracle会自动转换成 to_number(account_number) = 99999; 这样就抑制了索引的使用.

如果上面的语句加上单引号就会使用索引了
select bank_name,address,city,state,zip from banks where account_number='99999';

推荐阅读
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 在使用 DataGridView 时,如果在当前单元格中输入内容但光标未移开,点击保存按钮后,输入的内容可能无法保存。只有当光标离开单元格后,才能成功保存数据。本文将探讨如何通过调用 DataGridView 的内置方法解决此问题。 ... [详细]
  • 本文详细介绍了如何在 Linux 平台上安装和配置 PostgreSQL 数据库。通过访问官方资源并遵循特定的操作步骤,用户可以在不同发行版(如 Ubuntu 和 Red Hat)上顺利完成 PostgreSQL 的安装。 ... [详细]
  • 如何在PostgreSQL中查看数据表
    本文将指导您使用pgAdmin工具连接到PostgreSQL数据库,并展示如何浏览和查找其中的数据表。通过简单的步骤,您可以轻松访问所需的表结构和数据。 ... [详细]
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • 在使用SQL Server进行动态SQL查询时,如果遇到LIKE语句无法正确返回预期结果的情况,通常是因为参数传递方式不当。本文将详细探讨这一问题,并提供解决方案及相关的技术背景。 ... [详细]
  • 本文介绍如何通过创建替代插入触发器,使对视图的插入操作能够正确更新相关的基本表。涉及的表包括:飞机(Aircraft)、员工(Employee)和认证(Certification)。 ... [详细]
  • MySQL缓存机制深度解析
    本文详细探讨了MySQL的缓存机制,包括主从复制、读写分离以及缓存同步策略等内容。通过理解这些概念和技术,读者可以更好地优化数据库性能。 ... [详细]
  • SQLite 动态创建多个表的需求在网络上有不少讨论,但很少有详细的解决方案。本文将介绍如何在 Qt 环境中使用 QString 类轻松实现 SQLite 表的动态创建,并提供详细的步骤和示例代码。 ... [详细]
  • 精选30本C# ASP.NET SQL中文PDF电子书合集
    欢迎订阅我们的技术博客,获取更多关于C#、ASP.NET和SQL的最新资讯和资源。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 本文介绍如何在 FireDAC 环境下实现 FDMEMTable 字段的自动获取,为开发人员提供便捷的数据处理方式。 ... [详细]
author-avatar
王意之
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有