Oracle 基础篇 --- 索引

第四. 索引

4.1 定义

索引是与表关联的可选结构。通过创建索引可提高数据更新和检索的性能。Oracle 索引提供到数据行的直接访问路径。

可以对表的一个或多个列创建索引。创建索引后,Oracle 服务器会自动维护和使用索引。表数据的更新(如添加新行、更新行或删除行)会自动传播到所有相关的索引,这些对用户来说是完全透明的。

索引还可以提高实施主键和唯一键约束条件时的性能。如果没有索引,则每次对表执行DML 操作时都会扫描整个表(全表扫描)。

4.2 类型

有多种类型的索引结构,可以根据需要使用。最常用的两种
类型是:

4.2.1 B 树索引

默认的索引类型;
采用平衡树的形式.
B 树索引的键值存储在平衡树(B 树)中,这样可以快速执行二进制搜索。



B 树索引的结构

索引的顶层为根,它包含指向索引中下一层次的条目。下一层次为分支块,它又指向位于索引中下一层次的块。最底层是叶节点,它包含指向表行的索引条目。叶块是双向关联的,这便于按键值升序或降序扫描索引。



索引叶条目的格式

  • 条目头:存储列数和锁定信息
  • 键列长度/值对:用于定义键中的列大小,后面跟随列值(此类长度/值对的数目就是索引中的最大列数)。
  • ROWID:包含键值的行的行ID


索引叶条目的特性

在非分区表的B 树索引中:

  • 当多个行具有相同的键值时,如果不压缩索引,键值会出现重复
  • 当某行包含的所有键列为NULL 时,该行没有对应的索引条目。因此,当WHERE 子句指定了NULL 时,将始终执行全表扫描
  • 因为所有行属于同一个段,所以要使用受限的ROWID 指向表行


对索引执行DML 操作的效果

对表执行DML 操作时,Oracle 服务器会维护所有索引。下面说明对索引执行DML 命令产生的效果:

  • 执行插入操作导致在相应块中插入索引条目。
  • 删除一行只导致对索引条目进行逻辑删除。已删除行所占用的空间不可供后面新的叶条目使用。
  • 更新键列导致对索引进行逻辑删除和插入。PCTFREE设置对索引没有影响,但创建时除外。即使索引块的空间少于PCTFREE指定的空间,也可以向索引块添加新条目。

4.3 创建

#创建索引
create index emp3_name_ix on
emp3(emp3_name);

#查看索引的信息
select index_name, index_type, table_name, table_type, uniqueness, status
from user_indexes
where table_name = ‘EMP3‘;

INDEX_NAME      INDEX_TYPE      TABLE_NAME      TABLE_TYPE  UNIQUENES STATUS
--------------- --------------- --------------- ----------- --------- --------
EMP3_ID_PK      NORMAL          EMP3            TABLE       UNIQUE    VALID
EMP3_NAME_IX    NORMAL          EMP3            TABLE       NONUNIQUE VALID

#查看索引对应的列
SQL> select * from user_ind_columns where table_name = ‘EMP3‘;

INDEX_NAME      TABLE_NAME      COLUMN_NAME     COLUMN_POSITION COLUMN_LENGTH CHAR_LENGTH DESC
--------------- --------------- --------------- --------------- ------------- ----------- ----
EMP3_ID_PK      EMP3            EMP3_ID                       1            22           0 ASC
EMP3_NAME_IX    EMP3            EMP3_NAME                     1            10          10 ASC

SQL> select * from emp3 where emp3_name = ‘qa1‘;

   EMP3_ID EMP3_NAME      DEP_ID
---------- ---------- ----------
         2 qa1                 2

Execution Plan
----------------------------------------------------------
Plan hash value: 215206995

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

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

   2 - access("EMP3_NAME"=‘qa1‘)

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


4.4 决定使用全表扫描还是使用索引

在大多数情况下,全表扫描可能会导致更多的物理磁盘输入输出,但是全表扫描有时又可能会因为高度并行化的存在而执行的更快。

索引范围扫描的总体原则是:

  • 对于原始**排序的表**仅读取少于表记录数40%的查询应该使用索引范围扫描。
    反之,读取记录数目多于表记录数的40%的查询应该使用全表扫描。
  • 对于**未排序的表**仅读取少于表记录数7%的查询应该使用索引范围扫描。
    反之,读取记录数目多于表记录数的7%的查询应该使用全表扫描。
###决定使用全表扫描还是使用索引

SQL> select index_name, index_type, table_name, uniqueness, status from user_indexes where table_name = ‘EMP3‘;

INDEX_NAME      INDEX_TYPE TABLE_NAME      UNIQUENESS STATUS
--------------- ---------- --------------- ---------- --------
EMP3_ID_PK      NORMAL     EMP3            UNIQUE     VALID
EMP3_NAME_IX    NORMAL     EMP3            NONUNIQUE  VALID

SQL> select count(*) from emp3;

  COUNT(*)
----------
       19

#虽然有索引,但是此时是全表扫描
SQL> select * from emp3 where emp3_name = ‘qa8‘;

   EMP3_ID EMP3_NAME      DEP_ID
---------- ---------- ----------
        16 qa8                 2

Execution Plan
----------------------------------------------------------
Plan hash value: 2425169977

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    11 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP3 |     1 |    11 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter("EMP3_NAME"=‘qa8‘)

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

#往emp3表添加数据
[[email protected] sql]# more insert_data.sql
#!/bin/bash
i=$1;

while [ $i -le $2 ]
do
sqlplus hr/CCM%[email protected] <<EOF
insert into emp3 values($i,‘$3‘,$4);
commit;
quit;
EOF
let i=i+1
done

echo "inset into emp3 table"

[[email protected] sql]# ./insert_data.sql 90 100 dev 1

SQL> select max(emp3_id) from emp3;

MAX(EMP3_ID)
------------
      100000

SQL> analyze table emp3 estimate statistics;

Table analyzed.

SQL> select blocks, empty_blocks, num_rows from user_tables where table_name = ‘EMP3‘;

    BLOCKS EMPTY_BLOCKS   NUM_ROWS
---------- ------------ ----------
       374           10     101081

#查看一条数据
SQL> select * from emp3 where emp3_name = ‘qa33333‘;

   EMP3_ID EMP3_NAME      DEP_ID
---------- ---------- ----------
     33333 qa33333             2

Execution Plan
----------------------------------------------------------
Plan hash value: 215206995

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

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

   2 - access("EMP3_NAME"=‘qa33333‘)

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

#不加条件的查询,索引扫描
SQL> select count(*) from emp3;

  COUNT(*)
----------
    100000

Execution Plan
----------------------------------------------------------
Plan hash value: 2418373429

----------------------------------------------------------------------------
| Id  | Operation             | Name       | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |            |     1 |    70   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE       |            |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| EMP3_ID_PK |   101K|    70   (2)| 00:00:01 |
----------------------------------------------------------------------------

Statistics
----------------------------------------------------------
          2  recursive calls
          2  db block gets
        262  consistent gets
         37  physical reads
        176  redo size
        526  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

#没有创建索引的,查询全表扫描
SQL> select count(*) from emp3 where dep_id = 2;

  COUNT(*)
----------
     85726

Execution Plan
----------------------------------------------------------
Plan hash value: 1396384608

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     2 |   104   (1)| 00:00:02 |
|   1 |  SORT AGGREGATE    |      |     1 |     2 |            |          |
|*  2 |   TABLE ACCESS FULL| EMP3 | 50541 |    98K|   104   (1)| 00:00:02 |
---------------------------------------------------------------------------

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

   2 - filter("DEP_ID"=2)

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

SQL> select count(*) from emp3 where emp3_name like ‘qa%‘;

  COUNT(*)
----------
     85726

Execution Plan
----------------------------------------------------------
Plan hash value: 3884997069

----------------------------------------------------------------------------------
| Id  | Operation         | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |              |     1 |     8 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |              |     1 |     8 |            |          |
|*  2 |   INDEX RANGE SCAN| EMP3_NAME_IX |     7 |    56 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------

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

   2 - access("EMP3_NAME" LIKE ‘qa%‘)
       filter("EMP3_NAME" LIKE ‘qa%‘)

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

时间: 2024-10-12 14:23:12

Oracle 基础篇 --- 索引的相关文章

Oracle 基础篇 --- B树索引内部结构

内部结构 将B树索引转储成树状结构的形式而呈现出来: alter session set events 'immediate trace name treedump level INDEX_OBJECT_ID'; SQL> alter session set events 'immediate trace name treedump level 126545'; Session altered. [[email protected] trace]$ pwd /home/oracle/app/or

oracle(sql)基础篇系列(五)&mdash;&mdash;PLSQL、游标、存储过程、触发器

  PL/SQL PL/SQL 简介 每一种数据库都有这样的一种语言,PL/SQL 是在Oracle里面的一种编程语言,在Oracle内部使用的编程语言.我们知道SQL语言是没有分支和循环的,而PL语言是为了补充SQL语言的,是带有了分支和循环的语言. PL/SQL 语法 基本数据类型声明 declare v_name varchar2(20); v_temp number(1); v_count binary_integer := 0; v_sal number(7,2) := 4000.00

SQL Server调优系列基础篇(索引运算总结)

原文:SQL Server调优系列基础篇(索引运算总结) 前言 上几篇文章我们介绍了如何查看查询计划.常用运算符的介绍.并行运算的方式,有兴趣的可以点击查看. 本篇将分析在SQL Server中,如何利用先有索引项进行查询性能优化,通过了解这些索引项的应用方式可以指导我们如何建立索引.调整我们的查询语句,达到性能优化的目的. 闲言少叙,进入本篇的正题. 技术准备 基于SQL Server2008R2版本,利用微软的一个更简洁的案例库(Northwind)进行解析. 简介 所谓的索引应用就是在我们

SQL Server调优系列基础篇(联合运算符总结)

前言 上两篇文章我们介绍了查看查询计划的方式,以及一些常用的连接运算符的优化技巧,本篇我们总结联合运算符的使用方式和优化技巧. 废话少说,直接进入本篇的主题. 技术准备 基于SQL Server2008R2版本,利用微软的一个更简洁的案例库(Northwind)进行解析. 一.联合运算符 所谓的联合运算符,其实应用最多的就两种:UNION ALL和UNION. 这两个运算符用法很简单,前者是将两个数据集结果合并,后者则是合并后进行去重操作,如果有过写T-SQL语句的码农都不会陌生. 我们来分析下

ORACLE Index Lookup索引访问路径总结

在ORACLE中,索引访问/查找(Index Lookup)路径有五种方式,分别为INDEX UNIQUE SCAN.INDEX RANGE SCAN.INDEX FULL SCAN.INDEX FAST FULL SCAN .INDEX SKIP SCAN.下面通过一些案例介绍.总结一下这五种索引访问路径.本文是总结这方面的知识点,所以文中一些地方参考.引用了参考资料中的部分内容.详细.具体资料可以参考官方资料Index Scans 索引唯一扫描(INDEX UNIQUE SCAN)   索引

php面试题汇总二(基础篇附答案)

介绍一些php常见面试题及答案,都是平时面试的时候经常会遇到的,小伙伴们仔细了解下吧.接着上一篇php面试题汇总一(基础篇附答案) 1.在PHP中,当前脚本的名称(不包括路径和查询字符串)记录在预定义变量(1)中:而链接到当前页面的URL记录在预定义变量(2)中. 答:echo $_SERVER['PHP_SELF']; echo $_SERVER["HTTP_REFERER"]; 2:数组函数 arsort 的作用是(6):语句 error_reporting(2047)的作用是(7

Python之路【第十六篇】:Django【基础篇】

Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. 基本配置 一.创建django程序 终端命令:django-admin startproject sitename IDE创建Django程序时,本质上都是自动执行上述命令 其他常用命令: python manage.py runserver

Oracle SQL篇(一)null值之初体验

    从我第一次正式的写sql语句到现在,已经超过10年的时间了.我写报表,做统计分析和财务对账,我一点点的接触oracle数据库,并尝试深入了解.这条路,一走就是10年,从充满热情,到开始厌倦,我不知道我还能坚持多久,未来的路,谁知道呢? 也许是该抓紧时间,做一点什么了,我不知道该开始写些什么,我从来没有在网上写东西的习惯.     先从简单的开始吧,那当然就是SQL,这是我SQL系列的第一篇,希望我能够坚持. 在Oracle数据库中,如果一个表中的列没有值的话,我们可以说是空值,比如IT员

基础篇:6.Android数据库编程---SQLite

简介: 在Android平台上,继承了一个嵌入式关系型数据库---SQLite.SQLite具有跨平台特性,可以在所有主要的操作系统上运行.SQLite通过独占性和共享锁实现独立事务处理,因此多个进程可以在同一时间从同一数据库读取数据,但只有一个可以写入数据,在进行写操作之前,必须先获得独占锁.另一方面,SQLite采取动态数据类型,当某个值插入数据库时,SQLite会检查它的类型,如果该类型与所关联的列不匹配,SQLite则会进行强制转换.SQLite支持以下几种数据类型:NULL(空值).I