zoukankan      html  css  js  c++  java
  • Oracle_高级功能(2) 索引

    1.oracle优化器
    优化目标分为4种:
    choose (选择性)
    rule (基于规则)
    first rows(第一行)
    all rows(所有行)
    Description:描述sql的执行计划
    Object owner:对象模式
    Object name:对象名
    Cost:花费(的时间)
    Cardinality:基数,约等于行数
    Bytes:空间(访问的存储空间)

    2.table的访问方式
    2.1全表扫描(table access full)
    全表扫描就是顺序地访问表中每条记录。
    oracle采用一次读入多个数据块(database block)的方式优化全表扫描。
    举例:
    select * from emp;

    2.2通过rowid访问表(table access by user/index rowid)
    可以采用基于rowid的访问方式情况,提高访问表的效率。
    rowid包含了表中记录的物理位置信息。
    oracle采用索引(index)实现了数据和存放数据的物理位置(rowid)之间的联系。
    通常索引提供了快速访问rowid的方法,因此那些基于索引列的查询就可以得到性能上的提高。
    举例:
    select rowid,emp.* from emp where rowid='AAAR3sAAEAAAACXAAA';
    select * from emp where empno=7788;

    --清除数据库内存缓冲区
    alter system flush buffer_cache;

    索引(index)
    1.索引定义
    索引是一种与表相关联的可选结构,有时可以提高数据访问速度。
    通过在表中的一个或多个列上创建索引,
    通常情况下能够(快速地)从随机分布的表行中检索一小部分行。
    索引是减少磁盘 i/o 的许多手段之一。
    如果一个表没有索引,数据库必须执行全表扫描来查找值。
    测试:
    select * from all_objects;
    create table tab_all_objects as select * from all_objects;
    select * from tab_all_objects;
    35s-->26s
    select * from tab_all_objects where object_name='STUDENT';
    0.531s-->0.015s
    create index idx_object_name on tab_all_objects (object_name);
    练习:
    select owner,view_name,text_length,editioning_view,read_only from all_views;
    create table tab_all_views as select owner,view_name,text_length,editioning_view,read_only from all_views;
    select * from tab_all_views;
    0.515s-->0.498s
    select * from tab_all_views where view_name='VIEW_EMP';
    0.499s-->0.062s
    create index idx_view_name on tab_all_views (view_name);

    select * from emp,dept where emp.deptno=dept.deptno;
    0.109s-->0.031s
    create index idx_emp_deptno on emp (deptno);
    通常,在下列情况下可以考虑在某列上创建索引:
    某个列经常被作为查询条件,并且查询结果只返回了表中的一小部分行。5% >20%
    列或列集上存在引用完整性约束(是外键列)。

    二、语法
    2.1 创建索引
    create [unique | bitmap] index 索引名 on 表名 { ([<expr>] <col> [asc | desc] [, …])
    举例:
    create index idx_emp_deptno on emp (deptno); 普通索引
    create unique index idx_emp_ename on emp (ename); 唯一索引
    create index idx_emp_job_sal on emp (job,sal); 复合索引
    create index idx_emp_sal on emp (sal*12); 函数索引

    select * from emp where deptno=20;
    select * from emp where ename='FORD';
    select * from emp where job='MANAGER' and sal>=2500;
    select * from emp where sal*12>=20000;

    select * from tab_all_objects where object_id=74975;
    create index idx_object_id on tab_all_objects (object_id);

    --select * from tab_all_objects where object_type='SYNONYM';
    --create index idx_object_type on tab_all_objects (object_type);

    2.2 修改索引
    alter index <ind> {enable | disable};
    alter index <ind> rename to <new>;
    举例:
    alter index IDX_EMP_SAL disable;
    alter index idx_emp_deptno disable;
    alter index IDX_EMP_SAL rename to IDX_EMP_SAL1;
    alter index IDX_EMP_SAL1 rename to IDX_EMP_SAL;

    2.3 删除索引
    drop index <ind>;
    举例:
    --drop index IDX_EMP_SAL;

    2.4 分析索引
    analyze index <ind> validate structure online|offline;
    举例:
    analyze index IDX_EMP_SAL validate structure online;

    2.5 重建索引
    alter index <ind> rebuild
    举例:
    alter index IDX_EMP_SAL rebuild;

    --授权
    connect sys/123 as sysdba;
    grant create any index,drop any index,alter any index to scott;


    三、索引特征
    索引是一种模式对象,它在逻辑上和物理上都与其相关联表对象的数据保持独立。
    因此,可以删除或创建索引而不会实际影响相关的表。
    如果删除一个索引,应用程序将仍然可以工作。不过,访问之前通过索引访问的数据可能会变慢。
    索引的存在与否,不需要改变任何sql语句的写法。
    索引是到单一行数据的快速访问路径。它只影响执行的速度。
    对于一个已被索引的给定的数据值,索引直接指向包含该值的行的位置。
    在表上存在过多的索引,会降低dml性能,因为数据库还必须更新索引。
    主键和唯一键会自动生成索引,但需要手动在外键上创建索引。
    create index ind_emp_deptno on emp_test (deptno);
    select * from emp,dept where emp.deptno=dept.deptno;

    四、复合索引
    复合索引,也称为连接索引,是在某个表中的多个列上的索引。
    复合索引中的列应该以在检索数据的查询中最有意义的顺序出现,但在表中不必是相邻的。
    若 where 子句引用了复合索引中的所有列或前导列,
    复合索引可以加快 select 语句的数据检索速度。
    所以,在定义中所使用的列顺序很重要。一般地,最常被访问的列放在前面。

    五、唯一索引和非唯一索引
    索引可以是唯一的或非唯一的。
    唯一索引保证在表的键列或键列集上没有具有重复的值的行。
    在一个唯一索引中,对每个数据值都存在一个 rowid。叶块中的数据仅根据键排序。
    非唯一索引允许在索引的列或列集中有重复的值。
    对于非唯一索引,rowid 被包含在键中且已排序,
    因此非唯一索引按索引键和 rowid (升序) 进行排序。

    六、索引类型
    索引类型分为:b-树索引、位图索引、基于函数的索引

    6.1 b-树索引
    这是索引的标准类型。对于主键和高选择性索引非常适合。
    平衡树,简称b-树,是最常见的数据库索引类型。
    一个 b-树索引是被划分为多个范围的已排序的值列表。
    通过将键与一行或行范围关联起来 ,b-树可以对多种类型的查询提供优秀的检索性能,
    包括精确匹配和范围搜索等。

    二分查找算法是在有序数组中用到的较为频繁的一种算法。
    在未接触二分查找算法时,
    最通用的一种做法是,对数组进行遍历,跟每个元素进行比较,其时间为O(n).
    但二分查找算法则更优,因为其查找时间为O(lgn)。
    比如数组{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},查找元素6,
    用二分查找的算法执行的话,其顺序为:
    1.找中位数,用中位数和6比较,如果中位数比6大,则在中位数左侧数组中查找;如果中位数比6小,则在中位数右侧数组中查找;
    2.循环步骤1,直到等于要查找的值,并返回;或者找不到要查找的值,则返回空。

    select index_type,count(1) from dba_indexes where 1=1 group by index_type order by count(1) desc;
    1 NORMAL 3681
    2 LOB 901 BLOB、CLOB列产生的,非单独索引(view PLAN_TABLE$;)
    3 IOT - TOP 158 索引组织表的主键索引(view SQLLOG$;)
    4 FUNCTION-BASED NORMAL 40 基于函数的索引(view DBFS$_MOUNTS;)
    5 BITMAP 16 位图索引
    6 CLUSTER 10
    7 FUNCTION-BASED DOMAIN 4
    8 DOMAIN 1

    create bitmap index SH.SALES_PROD_BIX on SH.SALES (PROD_ID);


    6.2 位图索引
    在位图索引中,索引条目使用位图来指向多个行。
    create index idx_emp_deptno on emp (deptno);
    drop index idx_emp_deptno;
    create bitmap index idx_emp_deptno on emp (deptno);

    6.3 基于函数的索引
    这种类型的索引包括经过一个函数(如upper函数)转换过的列,或包括在表达式中的列。
    create index idx_emp_ename_lower on emp (lower(ename));

    七、索引扫描
    在索引扫描中,数据库使用语句指定的索引列,通过遍历索引来检索行。
    数据库扫描索引,将使用n个i/o就能找到其要查找的值,其中 n 即是b-树索引的高度。
    这是数据库索引背后的基本原理。
    如果 sql 语句仅访问被索引的列,那么数据库只需直接从索引中读取值,而不用读取表。
    如果该语句同时还需要访问除索引列之外的列,那么数据库会使用 rowid 来查找表中的行。
    通常,为检索表数据,数据库以交替方式先读取索引块,然后读取相应的表块。

    7.1.完全索引扫描 INDEX FULL SCAN
    select emp.* from emp,dept where emp.deptno=dept.deptno;
    在完全索引扫描中,数据库顺序读取整个索引。
    如果在 sql 语句中的谓词 (where 子句) 引用了一个索引列,
    或者在某些情况下未不指定任何谓词,此时可能使用完全索引扫描。
    完全扫描可以消除排序,因为数据本身就是基于索引键排过序的。


    7.2快速完全索引扫描 INDEX FAST FULL SCAN
    select view_name from tab_all_views;
    --all rows
    快速完全索引扫描是一种完全索引扫描,数据库并不按特定的顺序读取索引块。
    数据库仅访问索引本身中的数据,而无需访问表。
    当索引包含了查询所需的所有列,且索引键中至少一列具有 not null 约束时,快速完全索引扫描可以替代全表扫描。

    7.3 索引范围扫描 INDEX RANGE SCAN
    create index idx_emp_deptno on emp (deptno);
    select * from emp where deptno=10;
    索引范围扫描是对索引的有序扫描,具有以下特点:
    在条件中指定了一个或多个索引前导列。
    条件指定一个或多个表达式和逻辑 (布尔) 运算符的组合,并返回一个值( true、 false,或unknown)。
    一个索引键可能对应0个、1个或更多个值。
    通常,数据库使用索引范围扫描来访问选择性的数据。
    选择性是查询所选择的数据占总行数的百分比, 0 意味着没有任何行,1 表示所有行。
    选择性与一个(或多个)查询谓词相关,比如where last_name like 'a%'。
    值越接近 0的谓词越具有选择性,相反,越接近1的谓词则越不具有选择性。

    7.4 唯一索引扫描 INDEX UNIQUE SCAN
    select * from emp where empno=7788;

    相对于索引范围扫描,唯一索引扫描必须是 有0个 或 1个 rowid 与索引键相关联。
    当一个谓词使用相等运算符引用了唯一索引键的所有列时,数据库将执行唯一扫描。
    只要找到了第一个记录,唯一索引扫描就停止处理,因为不可能有第二个记录满足条件。

    7.5 索引跳跃扫描 INDEX SKIP SCAN
    如果在复合索引前导键列中有少量不同值,而在非前导键列中有大量不同值,此时使用跳跃扫描是有益的。
    --建表
    create table stu
    (
    sex varchar2(1) not null,
    sid number(8)
    );
    --建复合索引
    create index idx_stu_sexandsid on stu(sex,sid);
    --插数据
    declare
    begin
    for i in 1..1000 loop
    insert into stu values('M',i);
    end loop;
    for i in 1001..2000 loop
    insert into stu values('F',i);
    end loop;
    end;
    --分析表
    analyze table stu compute statistics;
    --分析SQL执行计划
    select * from stu where sid=100;
    索引跳跃扫描使用复合索引的逻辑子索引。
    数据库“跳跃地”通过单个索引,好像它在多个单独的索引中搜索一样。
    当在查询谓词中未指定组合索引的前导列时,数据库可能选择索引跳跃扫描。

    索引是根据指定的数据库表列建立起来的顺序。
    它提供了快速访问数据的途径,并且可监督表的数据,使其索引所指向的列中的数据不重复。
    分为单列索引和组合索引。
    主键、唯一键系统自动创建索引,外键系统不会自动创建索引。
    外键不创建索引时将导致父子表连接查询时出现子表的全表扫描。

    伪列rowid
    1.定义:
    oracle数据库的表中的每一行数据都有一个唯一的标识符,或者称为rowid,
    在oracle内部通常就是使用它来访问数据的。
    rowid需要 10个字节的存储空间,并用18个字符来显示。
    该值表明了该行在oracle数据库中的物理具体位置。
    可以在一个查询中使用rowid来表明查询结果中包含该值。
    select rowid,emp.* from emp where rowid='AAAR3sAAEAAAACXAAA';
    73196

    2.存储
    保存rowid需要10个字节或者是80个位二进制位。
    这80个二进制位分别是:
    1. 数据对象编号,表明此行所属的数据库对象的编号,每个数据对象在数据库建立的时候
    都被唯一分配一个编号,并且此编号唯一。数据对象编号占用大约32位。
    2. 对应文件编号,表明该行所在文件的编号,表空间的每一个文件标号都是唯一的。
    文件编号所占用的位置是10位。
    3. 块编号,表明改行所在文件的块的位置块编号需要22位。
    4. 行编号,表明该行在行目录中的具体位置行编号需要16位。
    这样加起来就是80位。

    3.显示
    Oracle的物理扩展ROWID有18位,每位采用64位编码,分别用A~Z、a~z、0~9、+、/共64个字符表示。
    A表示0,B表示1,……Z表示25,a表示26,……z表示51,0表示52,……,9表示61,+表示62,/表示63。
    64位编码表示的ROWID有18位,其中:
    数据对象编号占6位;
    文件编号占3位;
    块编号占6位;
    行编号占3位。
    select log(2,64),log(2,64)*18 from dual;

    4.举例:
    select rowid,empno,ename from emp;
    将会得到结果:
    AAAR3sAAEAAAACXAAA
    说明:
    AAAR3s是数据库对象编号,AAE是文件标号,AAAACX是块编号,最后三位AAA(SMITH)是行编号。

    5.验证
    5.1 验证行编号
    SMITH --> AAA
    ALLEN --> AAB
    不同人名 行号是递增的。
    5.2 验证数文件标号
    select FILE_ID as fid,FILE_NAME from dba_data_files where TABLESPACE_NAME='USERS' ;
    FID FILE_NAME
    ---------- ---------------------------------------------
    4 D:APPWANGXUWEIORADATAORCLUSERS01.DBF
    FILE_ID=4,就是ROWID中AAE。
    5.3 验证数据库对象编号
    select * from dba_objects where object_name='EMP';
    objectid
    73196
    73196 = AAAR3s ???
    select ascii('R')-ascii('A') from dual;
    R=17=17×64×64

    3=26+26+3=55
    select ascii('s')-ascii('a')+26 from dual;
    s=44
    AAAR3s=17×64×64+55×64+44
    select 17*64*64+55*64+44 from dual;
    73196

    5.4 验证块编号
    select * from dba_extents where segment_name='EMP';
    extent_id =0
    file_id =4
    block_id =144
    bytes =65536
    blocks =8
    144 = AAAACX ???
    select ascii('X')-ascii('A') from dual;
    23
    AAAACX=2×64+23=
    select 2*64+23 from dual;
    151
    AAAACX=151<>144 ???

    6.dbms_rowid包
    通过dbms_rowid包,可以直接得到具体的rowid包含的信息:
    select dbms_rowid.rowid_object(rowid) object_id,
    dbms_rowid.rowid_relative_fno(rowid) file_id,
    dbms_rowid.rowid_block_number(rowid) block_id,
    dbms_rowid.rowid_row_number(rowid) row_number,
    rowid,emp.*
    from emp;

    通过dbms_rowid包,还可以查询到表或记录所在的文件
    select file_id,file_name from dba_data_files
    where file_id in (select distinct dbms_rowid.rowid_relative_fno(rowid) from scott.emp);
    file_id file_name
    4 D:APPORADATAORCLUSERS01.DBF

  • 相关阅读:
    投行风云:FO的酸甜苦辣【转】
    周末排毒
    LeetCode | Single Number II【转】
    Adding supplementary tables and figures in LaTeX【转】
    Algorithm | Tree traversal
    Leetcode | Linked List Cycle I && II
    Network | UDP checksum
    Ubuntu下将现有的文件打包成deb包
    Base64编码加密
    requestAnimationFrame 的原理与优势
  • 原文地址:https://www.cnblogs.com/BradMiller/p/9279753.html
Copyright © 2011-2022 走看看