Oracle数据库中的索引详解

Oracle数据库中的索引详解,第1张

一 ROWID的概念

存储了row在数据文件中的具 置 位编码的数据 A Z a z + 和 /

row在数据块中的存储方式

SELECT ROWID last_name FROM hr employees WHERE department_id = ;

比如 OOOOOOFFFBBBBBBRRR

OOOOOO data object number 对应dba_objects data_object_id

FFF file# 对应v$datafile file#

BBBBBB block#

RRR row#

Dbms_rowid包

SELECT dbms_rowid rowid_block_number( AAAGFqAABAAAIWEAAA ) from dual;

具体到特定的物理文件

索引的概念

类似书的目录结构

Oracle 的 索引 对象 与表关联的可选对象 提高SQL查询语句的速度

索引直接指向包含所查询值的行的位置 减少磁盘I/O

与所索引的表是相互独立的物理结构

Oracle 自动使用并维护索引 插入 删除 更新表后 自动更新索引

语法 CREATE INDEX index ON table (column[ column] );

B tree结构(非bitmap)

[一]了解索引的工作原理

表 emp

目标 查询Frank的工资salary

建立索引 create index emp_name_idx on emp(name);

[试验]测试索引的作用

运行/rdbms/admin/utlxplan 脚本

建立测试表

create table t as select from dba_objects;

insert into t select from t;

create table indextable

as select rownum id owner object_name subobject_name

object_id data_object_id object_type created

from t;

set autotrace trace explain

set timing on

分析表 可以得到cost

查询 object_name= DBA_INDEXES

在object_name列上建立索引

再查询

[思考]索引的代价

插入 更新

三 唯一索引

何时创建 当某列任意两行的值都不相同

当建立Primary Key(主键)或者Unique constraint(唯一约束)时 唯一索引将被自动建立

语法 CREATE UNIQUE INDEX index ON table (column);

演示

四 组合索引

何时创建 当两个或多个列经常一起出现在where条件中时 则在这些列上同时创建组合索引

组合索引中列的顺序是任意的 也无需相邻 但是建议将最频繁访问的列放在列表的最前面

演示(组合列 单独列)

五 位图索引

何时创建

列中有非常多的重复的值时候 例如某列保存了 性别 信息

Where 条件中包含了很多OR *** 作符

较少的update *** 作 因为要相应的跟新所有的bitmap

结构 位图索引使用位图作为键值 对于表中的每一数据行位图包含了TRUE( ) FALSE( ) 或NULL值

优点 位图以一种压缩格式存放 因此占用的磁盘空间比标准索引要小得多

语法 CREATE BITMAP INDEX index ON table (column[ column] );

掩饰

create table bitmaptable as select from indextable where owner in( SYS PUBLIC );

分析 查找 建立索引 查找

六 基于函数的索引

何时创建 在WHERE条件语句中包含函数或者表达式时

函数包括 算数表达式 PL/SQL函数 程序包函数 SQL函数 用户自定义函数

语法 CREATE INDEX index ON table (FUNCTION(column));

演示

必须要分析表 并且query_rewrite_enabled=TRUE

或者使用提示/+ INDEX(ic_index)/

七 反向键索引

目的 比如索引值是一个自动增长的列

多个用户对集中在少数块上的索引行进行修改 容易引起资源的争用 比如对数据块的等待 此时建立反向索引

性能问题

语法

重建为标准索引 反之不行

八 键压缩索引

比如表landscp的数据如下

site feature job

Britten Park Rose Bed Prune

Britten Park Rose Bed Mulch

Britten Park Rose Bed Spray

Britten Park Shrub Bed Mulch

Britten Park Shrub Bed Weed

Britten Park Shrub Bed Hoe

……

查询时 以上 列均在where条件中同时出现 所以建立基于以上 列的组合索引 但是发现重复值很多 所以考虑压缩特性

Create index zip_idx

on landscp(site feature job)

press ;

将索引项分成前缀(prefix)和后缀(postfix)两部分 前两项被放置到前缀部分

Prefix : Britten Park Rose Bed

Prefix : Britten Park Shrub Bed

实际所以的结构为

Prune

Mulch

Spray

Mulch

Weed

Hoe

特点 组合索引的前缀部分具有非选择性时 考虑使用压缩 减少I/O 增加性能

九 索引组织表(IOT)

将表中的数据按照索引的结构存储在索引中 提高查询速度

牺牲插入更新的性能 换取查询性能 通常用于数据仓库 提供大量的查询 极少的插入修改工作

必须指定主键 插入数据时 会根据主键列进行B树索引排序 写入磁盘

十 分区索引

簇:

A cluster is a group of tables that share the same data blocks because they share mon columns and are often used together

lishixinzhi/Article/program/Oracle/201311/17769

什么是索引:

索引是数据库存储引擎用于快速查找到指定数据的一种数据结构。

可以用新华字典做类比:如果新华字典中对每个字的详细解释是数据库中表的记录,那么按部首或拼音等排序的目录就是索引,使用它可以让我们快速查找的某一个字详细解释的位置。

在MySQL中,存储引擎也是用了类似的方法,先在索引中找到对应的值,然后再根据匹配的索引值找到对应表中记录的位置。

面试中为什么问索引:

之所以在索引在面试中经常被问到,就是因为:索引是数据库的良好性能表现的关键,也是对查询能优化最有效的手段。索引能够轻易地把查询性能提高几个数量级。

然而,糟糕的索引也同样会影响查询性能,当表中的数据量越来越多的时候,索引对性能的影响就越大。在数据量比较少并且负责比较低的时候,糟糕的索引对性能的影响可能不明显,但是当数据量逐渐增多的时候,性能会急剧下降。

索引的类型:

不同类型的索引,可以为不同场景提供更好的性能。在MySQL中,索引是在存储引擎层面实现的,而不是在服务器层面实现的。正如大家所知道,MySQL支持多种类型的存储引擎。所以,在不同存储引擎中索引的实现方式并不是一样的,也不是所有类型的索引都被所有存储引擎支持的,即使多个存储引擎支持同一种类型的索引,它底层的实现也有可能是不相同的。

先正面回答你的问题

数据是否重复不是建立索引的重要依据,甚至都不是依据。

只要不完全重复(所有元组的该元素都一样),那么建立索引就是有意义的。

即使当前数据完全重复,也不是不能建立索引,这种情况有点复杂,不细说了。

对于你后面的疑问,可以给你一个如何建立索引的忠告,“如何查就如何建”。

索引的建立,唯一的原因就是为了查询(广义的查询),实际上建立索引会使得数据存储所占空间变大,有时索引所占的空间会查过数据本身的空间。索引的建立也会使得数据插入时变慢,特殊情况下,慢的难以忍受,所以dba的重要工作之一,就是检查索引层级并优化。

索引建立的唯一好处,就是按照索引查询时,变快了。type,status这2个字段是否适合建立索引,就要看你是否要按照这2个字段进行检索。而检索的顺序决定了如何建立索引。

对于索引类型和索引方式,我建议就

normal

btree

就适用于大多数情况。若你参与的是一个大数据处理项目,对数据存储和检索有特别要求,那么需要分析多个层面,比如数据吞吐量、数据的方差、平均差等等很多参数才考虑是否用聚集索引等(mysql好像还没聚集索引),至于是否是唯一索引,我建议不使用,即使能判定数据是唯一的也不要用,全文索引也没有必要。

选择开始菜单中→程序→management

sql

server

2008→sql

server

management

studio命令,打开sql

server

management

studio窗口,并使用windows或

sql

server身份验证建立连接。

在对象资源管理器窗口中展开服务器,然后选择数据库节点

右键单击数据库节点,从d出来的快捷菜单中选择新建数据库命令。

执行上述 *** 作后,会d出新建数据库对话框。在对话框、左侧有3个选项,分别是常规、选项和文件组。完成这三个选项中的设置会后,就完成了数据库的创建工作,

在数据库名称文本框中输入要新建数据库的名称。例如,这里以“新建的数据库”。

在所有者文本框中输入新建数据库的所有者,如sa。根据数据库的使用情况,选择启用或者禁用使用全文索引复选框。

在数据库文件列表中包括两行,一行是数据库文件,而另一行是日记文件。通过单击下面的添加、删除按钮添加或删除数据库文件。

切换到选项页、在这里可以设置数据库的排序规则、恢复模式、兼容级别和其他属性。

切换到文件组页,在这里可以添加或删除文件组。

完成以上 *** 作后,单击确定按钮关闭新建数据库对话框。至此“新建的数据”数据库创建成功。新建的数据库可以再对象资源管理器窗口看到。

1合理使用索引\x0d\索引是数据库中重要的数据结构,它的根本目的就是为了提高查询效率。现在大多数的数据库产品都采用IBM最先提出的ISAM索引结构。\x0d\索引的使用要恰到好处,其使用原则如下:\x0d\在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化器自动生成索引。\x0d\在频繁进行排序或分组(即进行group by或order by *** 作)的列上建立索引。\x0d\在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。\x0d\如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。\x0d\使用系统工具。如Informix数据库有一个tbcheck工具,可以在可疑的索引上进行检查。在一些数据库服务器上,索引可能失效或者因为频繁 *** 作而 使得读取效率降低,如果一个使用索引的查询不明不白地慢下来,可以试着用tbcheck工具检查索引的完整性,必要时进行修复。另外,当数据库表更新大量 数据后,删除并重建索引可以提高查询速度。\x0d\(1)在下面两条select语句中:\x0d\SELECT FROM table1 WHERE field1=0; \x0d\SELECT FROM table1 WHERE field1>=0 AND field1=0,则第一条select语句要比第二条select语句效率高的多,因为第二条select语句的第一个条件耗费了大量的系统资源。\x0d\第一个原则:在where子句中应把最具限制性的条件放在最前面。\x0d\(2)在下面的select语句中:\x0d\SELECT FROM tab WHERE a= AND b= AND c=;\x0d\若有索引index(a,b,c),则where子句中字段的顺序应和索引中字段顺序一致。\x0d\第二个原则:where子句中字段的顺序应和索引中字段顺序一致。\x0d\—————————————————————————— \x0d\以下假设在field1上有唯一索引I1,在field2上有非唯一索引I2。 \x0d\—————————————————————————— \x0d\(3) SELECT field3,field4 FROM tb WHERE field1='sdf' 快 \x0d\SELECT FROM tb WHERE field1='sdf' 慢[/cci]\x0d\因为后者在索引扫描后要多一步ROWID表访问。\x0d\(4) SELECT field3,field4 FROM tb WHERE field1>='sdf' 快 \x0d\SELECT field3,field4 FROM tb WHERE field1>'sdf' 慢\x0d\因为前者可以迅速定位索引。\x0d\(5) SELECT field3,field4 FROM tb WHERE field2 LIKE 'R%' 快 \x0d\SELECT field3,field4 FROM tb WHERE field2 LIKE '%R' 慢,\x0d\因为后者不使用索引。\x0d\(6) 使用函数如: \x0d\SELECT field3,field4 FROM tb WHERE upper(field2)='RMN'不使用索引。\x0d\如果一个表有两万条记录,建议不使用函数;如果一个表有五万条以上记录,严格禁止使用函数!两万条记录以下没有限制。\x0d\(7) 空值不在索引中存储,所以 \x0d\SELECT field3,field4 FROM tb WHERE field2 IS[NOT] NULL不使用索引。\x0d\(8) 不等式如 \x0d\SELECT field3,field4 FROM tb WHERE field2!='TOM'不使用索引。 \x0d\相似地, \x0d\SELECT field3,field4 FROM tb WHERE field2 NOT IN('M','P')不使用索引。\x0d\(9) 多列索引,只有当查询中索引首列被用于条件时,索引才能被使用。\x0d\(10) MAX,MIN等函数,使用索引。 \x0d\SELECT max(field2) FROM tb 所以,如果需要对字段取max,min,sum等,应该加索引。\x0d\一次只使用一个聚集函数,如: \x0d\SELECT “min”=min(field1), “max”=max(field1) FROM tb \x0d\不如:SELECT “min”=(SELECT min(field1) FROM tb) , “max”=(SELECT max(field1) FROM tb)\x0d\(11) 重复值过多的索引不会被查询优化器使用。而且因为建了索引,修改该字段值时还要修改索引,所以更新该字段的 *** 作比没有索引更慢。\x0d\(12) 索引值过大(如在一个char(40)的字段上建索引),会造成大量的I/O开销(甚至会超过表扫描的I/O开销)。因此,尽量使用整数索引。 Sp_estspace可以计算表和索引的开销。\x0d\(13) 对于多列索引,ORDER BY的顺序必须和索引的字段顺序一致。\x0d\(14) 在sybase中,如果ORDER BY的字段组成一个簇索引,那么无须做ORDER BY。记录的排列顺序是与簇索引一致的。\x0d\(15) 多表联结(具体查询方案需要通过测试得到) \x0d\where子句中限定条件尽量使用相关联的字段,且尽量把相关联的字段放在前面。 \x0d\SELECT afield1,bfield2 FROM a,b WHERE afield3=bfield3\x0d\field3上没有索引的情况下: \x0d\对a作全表扫描,结果排序 \x0d\对b作全表扫描,结果排序 \x0d\结果合并。 \x0d\对于很小的表或巨大的表比较合适。\x0d\field3上有索引 \x0d\按照表联结的次序,b为驱动表,a为被驱动表 \x0d\对b作全表扫描 \x0d\对a作索引范围扫描 \x0d\如果匹配,通过a的rowid访问\x0d\(16) 避免一对多的join。如: \x0d\SELECT tb1field3,tb1field4,tb2field2 FROM tb1,tb2 WHERE tb1field2=tb2field2 AND tb1field2=‘BU1032’ AND tb2field2= ‘aaa’ \x0d\不如: \x0d\declare @a varchar(80) \x0d\SELECT @a=field2 FROM tb2 WHERE field2=‘aaa’ \x0d\SELECT tb1field3,tb1field4,@a FROM tb1 WHERE field2= ‘aaa’\x0d\(16) 子查询 \x0d\用exists/not exists代替in/not in *** 作 \x0d\比较: \x0d\SELECT afield1 FROM a WHERE afield2 IN(SELECT bfield1 FROM b WHERE bfield2=100) \x0d\SELECT afield1 FROM a WHERE EXISTS( SELECT 1 FROM b WHERE afield2=bfield1 AND bfield2=100) \x0d\SELECT field1 FROM a WHERE field1 NOT IN( SELECT field2 FROM b) \x0d\SELECT field1 FROM a WHERE NOT EXISTS( SELECT 1 FROM b WHERE bfield2=afield1)\x0d\(17) 主、外键主要用于数据约束,sybase中创建主键时会自动创建索引,外键与索引无关,提高性能必须再建索引。\x0d\(18) char类型的字段不建索引比int类型的字段不建索引更糟糕。建索引后性能只稍差一点。\x0d\(19) 使用count()而不要使用count(column_name),避免使用count(DISTINCT column_name)。\x0d\(20) 等号右边尽量不要使用字段名,如: \x0d\SELECT FROM tb WHERE field1 = field3\x0d\(21) 避免使用or条件,因为or不使用索引。\x0d\2避免使用order by和group by字句。\x0d\因为使用这两个子句会占用大量的临时空间(tempspace),如果一定要使用,可用视图、人工生成临时表的方法来代替。 \x0d\如果必须使用,先检查memory、tempdb的大小。 \x0d\测试证明,特别要避免一个查询里既使用join又使用group by,速度会非常慢!\x0d\3尽量少用子查询,特别是相关子查询。因为这样会导致效率下降。\x0d\一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次。查询嵌套层次越多,效率越低,因此应当尽量避免子查询。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行。\x0d\4.消除对大型表行数据的顺序存取\x0d\在 嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。 \x0d\比如采用顺序存取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询 10亿行数据。 \x0d\避免这种情况的主要方法就是对连接的列进行索引。 \x0d\例如,两个表:学生表(学号、姓名、年龄)和选课表(学号、课程号、成绩)。如果两个 表要做连接,就要在“学号”这个连接字段上建立索引。 \x0d\还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引,但某些形式的where子句强迫优化器使用顺序存取。 \x0d\下面的查询将强迫对orders表执行顺序 *** 作: \x0d\SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008 \x0d\虽然在customer_num和order_num上建有索引,但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。因为这个语句要检索的是分离的行的集合,所以应该改为如下语句: \x0d\SELECT * FROM orders WHERE customer_num=104 AND order_num>1001 \x0d\UNION \x0d\SELECT * FROM orders WHERE order_num=1008 \x0d\这样就能利用索引路径处理查询。\x0d\5.避免困难的正规表达式\x0d\MATCHES和LIKE关键字支持通配符匹配,技术上叫正规表达式。但这种匹配特别耗费时间。例如:SELECT * FROM customer WHERE zipcode LIKE “98_ _ _” \x0d\即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。如果把语句改为SELECT * FROM customer WHERE zipcode >“98000”,在执行查询时就会利用索引来查询,显然会大大提高速度。 \x0d\另外,还要避免非开始的子串。例如语句:SELECT * FROM customer WHERE zipcode[2,3] >“80”,在where子句中采用了非开始子串,因而这个语句也不会使用索引。\x0d\6.使用临时表加速查询\x0d\把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序 *** 作,而且在其他方面还能简化优化器的工作。例如: \x0d\SELECT custname,rcvblesbalance,other COLUMNS \x0d\FROM cust,rcvbles \x0d\WHERE custcustomer_id = rcvlbescustomer_id \x0d\AND rcvbllsbalance>0 \x0d\AND custpostcode>“98000” \x0d\ORDER BY custname \x0d\如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个临时文件中,并按客户的名字进行排序: \x0d\SELECT custname,rcvblesbalance,other COLUMNS \x0d\FROM cust,rcvbles \x0d\WHERE custcustomer_id = rcvlbescustomer_id \x0d\AND rcvbllsbalance>;0 \x0d\ORDER BY custname \x0d\INTO TEMP cust_with_balance \x0d\然后以下面的方式在临时表中查询: \x0d\SELECT * FROM cust_with_balance \x0d\WHERE postcode>“98000” \x0d\临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。 \x0d\注意:临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下,注意不要丢失数据。\x0d\7.用排序来取代非顺序存取\x0d\非顺序磁盘存取是最慢的 *** 作,表现在磁盘存取臂的来回移动。SQL语句隐藏了这一情况,使得我们在写应用程序时很容易写出要求存取大量非顺序页的查询。

应该建索引的字段:1经常作为查询条件的字段2外键3经常需要排序的字段4分组排序的字段

应该少建或者不建索引的字段有:1表记录太少,2经常需要插入,删除,修改的表,3表中数据重复且分布平均的字段

一些SQL的写法会限制索引的使用:1where子句中如果使用in、or、like、!=,均会导致索引不能正常使用,将""换成">and=chr(0)";2使用函数时,该列就不能使用索引。3比较不匹配数据类型时,该索引将会被忽略。

一些SQL语句优化的写法:1如果from是双表的查询时,大表放在前面,小表放在后面(基础表)。最后面的表是基础表。(只在基于规则的优化器中有效)2如果三表查询时,选择交叉表(table)作为基础表(只在基于规则的优化器中有效)3写where条件时,有索引字段的判断在前,其它字段的判断在后;如果where条件中用到复合索引,按照索引列在复合索引中出现的顺序来依次写where条件;4查询数量较大时,使用表连接代替IN,EXISTS,NOTIN,NOTEXISTS等。5ORACLE采用自下而上的顺序解析WHERE子句,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾

以上就是关于Oracle数据库中的索引详解全部的内容,包括:Oracle数据库中的索引详解、数据库中的索引是什么意思、数据库中的索引有什么用等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9727536.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存