数据库之序列/视图/索引

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/My_ben/article/details/83006987

序列

序列概述
序列是一个命名的顺序编号生成器,它能以串行的方式生成一系列顺序整数。与视图、约束相似,序列不占用实际的存储空间,而只在数据字典中保存序列的定义。引入序列的理由或序列的主要用途主要有以下3点。
⑴ 主键、外键值应用需求
在某些表中,主键可以需要由多个字段组成,如果将这些字段合起来作为主键。就会将问题复杂化。因此,可以使用简单的顺序号来代替多个字段的主键标识记录,以简化子表对于父表的引用关系。如果在一个数据库中应用中创建一个序列,使各个表都使用该序列产生的整数作为主键、外键值,则会对数据库的设计、编程、各种主键和外键关系的建立都起到良好的作用。
⑵ 流水号应用需求
在现实生活中,流水号使用较为频繁。例如,商场打印销售单时需要将销售单按顺序编号,每张销售单对应一个编号,且编号是依次递增的。在Oracle中,可以使用序列产生的单据流水号。
⑶ 序列的生成与定义的内容
序列由Oracle服务器端产生,所有的序列都出自一处。如果有多个用户同时向序列提出申请,则序列会按照串行机制一次处理各个用户的请求,绝不会生成两个相同的整数。而且即使在并发用户数量很多的联机事物处理环境中,序列也会快速生成一个整数,不会产生明显的延迟。
注意:序列能生成最大为38位的整数。
创建序列
需要在自己的解决方案中创建序列时,用户必须具有CREATE SEQUEECU系统权限;在其他解决方案中创建序列时,用户必须具有CREAT ANY SEQUENCE系统权限。
语法:
CREATE SEQUENCE sequnce_name
[START WITH n1]
[INCREMENT BY n2]
[{MAXVALUE n3 | NOMAXVALUE}]
[{MINVALUE n4 | NOMINVALUE}]
[{CACHE n5 | NOCACHE}]
[{CYCLE  | NOCYCLE}]
[ORDER]

语法说明:
⑴ START WITH:指定要生成的第一个序列号
⑵ INCREMENT BY:用于指定序列号之间的间隔,默认为1。n为正值,则生成的序列将按升序排列,n为负值,则反之。
⑶ MAXVALUE :指定序列可以生成的最大值,必须大于等于START WITH中的n1,并大于MINVALUE 中的n4。
⑷ NOMAXVALUE:用于指定序列没有上限,最大值可达1027。
⑸ MINVALUE :指定序列可以生成的最小值,必须小于等于START WITH中的n1,并小于MAXVALUE 中的n3。
⑹ NOMINVALUE:用于指定序列没有下限,最大值可达10-26。
⑺ CACHE :用于指定在高速缓存中可以预分配的序列号个数,默认为20。
⑻ NOCACHE:用于之低昂在高速缓存中不预先分配序列号,即序列生成器会每次生成一个序列号。
⑼ CYCLE:用于指定在达到序列的最大值或最小值后是否循环,即再次从n1开始生成序列号。
⑽ ORDER:用于指定按顺序生成序列号。
SCOTT用户创建了一个seq_id序列,利用该序列可以为其方案中的表生成唯一的整数。该序列从300开始,每次增量为1,最大值为99999999,每次生成10个序列号,达到最大值后不循环。代码如下:

SQL> conn scott/tiger@scce
create sequence seq_id
increment by 1
start with 300
maxvalue 99999999
cache 10 
nocycle
使用序列
◇ NETTVAL 和 CURRVAL 列
在引用序列时,需要使用序列的NETTVAL 和 CURRVAL 两个列。NETTVAL 列返回序列生成的下一个值, CURRVAL列返回序列生成的当前值。
◇ 序列的初始化
在第一次引用CURRVAL 列之前,必须引用过一次NETTVAL 列,用于初始化序列的值,否则会报错。
◇ 在SQL语句中使用序列
在SQL语句中,可以直接使用引用序列的值。首先创建一张tb_test表,然后使用seq_id序列生成的整数作为该表的主键值。
更改序列
需要更改自己方案中的序列时,用户必须具有ALTER SEQUENCE系统权限;更改其他方案中的序列时,用户必须具有ALTER ANY SEQUENCE系统权限。更改序列时,不能修改序列中的起始值,修改起始值必须删除序列再重建。更改序列包括以下3种:
⑴ 修改MAXVALUE和MINVALUE
⑵ 修改INCREMENT增量值
⑶ 修改缓存中的序列的数目
语法:
ALTER SEQUENCE sequence_name
[INCREMENT BY n2]
[{MAXVALUE n3 | NOMAXVALUE}]
[{MINVALUE n4 | NOMINVALUE}]
[{CACHE n5 | NOCACHE}]
[{CYCLE  | NOCYCLE}]
删除序列
需要删除自己方案中的序列时,用户必须具有 DROP SEQUENCE 系统权限;删除其他方案中的序列时,用户必须具有 DROP ANY SEQUENCE 系统权限。
语法:
DROP SEQUENCE sequence_name

视图

视图概述
视图是由SELECT子查询语句定义的逻辑表,它只有定义,没有数据,是一个“虚表”。视图是查看和操作数据的一种方法。
使用视图有诸多优点,如提供各种数据表现形式、提供某些数据的安全性、隐藏数据的复杂性、简化查询语句、执行特殊查询、保存复杂查询等。在许多情况下,视图的使用和管理都与表相似,例如都可以被创建、更改和删除,都可以通过它们来操作数据库中的数据。除了SELECT之外,视图在INSERT、UPDATE和DELETE方面受到了限制。
创建视图
在当前的方案中创建视图时,用户必须具有CREATE VIEW系统权限;在其他方案中创建视图时,用户必须具有CREATE ANY VIEW系统权限。视图的拥有者必须被明确授予访问者在视图定义中所参考的所有基础对象的权限。例如,如果视图的拥有者只具有在SCOTT方案中的emp表中插入新行,而不能进行SELECT、UPDATE、DELETE等操作。
语法:
CREATE [OR REPLACE]  [FORCE] VIEW view_name
[(alias1,ailas2...)]
AS select_statement
[WITH CHECK OPTION [CONSTRAINT constraint] ]
[WITH REAN ONLY]

语法说明:
⑴ OR REPLACE:如果视图已存在,该选项将重新创建该视图。
⑵ FORCE:无论基表(实表)是否存在,都将创建视图。
⑶ view_name:视图名。
⑷ alias:指定由视图的查询所选择的表达式或列的别名。
【注意】别名的数目必须与视图所选择的表达式的数目匹配。
⑸ select_statement:创建视图是的SELECT语句。
⑹ WITH CHECK OPTION:在使用视图时,检查涉及的数据是否能通过SELECT查询的WHERE条件。
⑺ WITH REAN ONLY:创建的实体只能用于查询,而不能由于更改数据。
【注意】该子句不能与ORDER BY子句同时存在。

强制创建视图
正常情况下,如果基本表不存在,则创建视图会失败;但如果创建视图的语句没有语法错误,则只要使用FORCE选项即可创建该视图,这种强制创建的视图被称为带有编译错误的视图。此时,视图处于失效状态,不能执行,但之后随着基础表的创建,该视图就可以正常执行了。Oracle之所以提供强制创建视图的功能,是为了使基础表的创建和修改与视图的创建和修改之间没有必然的依赖性,从而便于同步工作、提高工作效率。
在连接视图上执行DML操作
在视图上进行的所有DML操作最终都会在基础表的数据上完成。与普通表相同,可以对视图进行SELECT操作,但对视图进行更新(包括UPDATE、 DELETE 、INSERT)操作则会受到某些限制,即并非所有的视图上都可以执行全部的DML操作。
对于一个基于基础表的简单视图而言,它只是简单的去掉可基础表的某些记录或某些列,但如果视图中包括基础表的键(主键、外键),则总可以在其上进行DML操作。
与简单视图相对应,如果一个视图基于多个基础表(或视图),即定义视图的查询时一个连接查询,该视图被称为连接视图。有些连接视图可以更新,但有些不能更新。
◇ 可更新连接视图
当创建连接视图的SELECT子句满足以下条件时,连接视图可以更新:
⑴ 不包含集中运算符(UNION、 UNION 、ALL INTERSECT 、MINUS等)。
⑵ 不包含DISTINCT关键字。
⑶ 不包含ORDER BY 、GROUP BY 、CONNECT BY或START WITH子句。
⑷ 不包含子查询。
⑸ 不包含分组函数。
⑹ 需要更新的列不是由列表达式定义的。
⑺ 表中所有的NOT NULL列均属于该视图。
上述只是最基本的条件,即并非在可更新连接视图中就可以进行更新操作,还需要遵守更新标准,只能对“键值保存表”进行更新。
◇ 键值保存表
如果连接视图中的一个基础表的主键(主键、唯一键)在它的视图中仍然存在,则称该基础表为键值保存表。一般而言,在由父子关系的两个表组成的连接视图中,子表就是键值保存表。
查询视图信息
◇ 查询视图的可更新列
使用USER_UPDATABLE_COLUMNS数据字典可以查询当前用户方案中所有的表以及视图中所有课修改的列。
◇ 查询视图的定义信息
使用USER_VIEWS数据字典可以查询当前方案中视图的定义信息。
删除视图
当前模式中的各种视图都可以删除,但删除其他方案中的视图时必须拥有DROP ANY VIEW系统权限。
语法:
DROP VIEW view_name

索引

索引概述
索引就是一种与表相关的可选的方案对象。通过在表中的一个或多个列上创建索引,就能为数据的检索提供快捷的存取路径,减少查询时硬盘I/O操作,加快数据的索引速度。与其他具有独立存储结构的方案对象类似,索引需要占用实际的存储空间。一旦创建了索引,在表上执行DML操作时,Oracle就会自动的对索引进行维护,并且由Oracle决定何时使用索引,用户完全不用考虑在SQL语句中指定使用那个索引以及如何使用索引。如果将表看成一本书,则索引的作用类似于书的目录。需要在表中查询指定的记录时,在没有索引的情况下,必须遍历整张表中的记录;但如果存在索引,则只需要现在索引中找到符合查询条件的索引列值,然后通过保存索引中的ROWID快速查找表中对应的记录。
创建索引
可以使用CREATE INDEX 命令在一列或若干列的组合上创建索引,在自己的方案中创建索引时,必须拥有CREATE VIEW INDEX系统权限;在其他用户的方案中创建索引时,必须拥有CREATE ANY INDEX系统权限。
语法:
CREATE INDEX index_name pn table_name(column list)
[TABLESPACE tablespace_name]

语法说明:
⑴ index_name:指定所创建的索引名。
⑵ table_name:指定创建索引的表名。
⑶ column_list:指定在表上创建索引的列名列表,可以基于多列创建索引。
⑷ tablespace_name:为索引指定表空间。
在创建索引时,会对表进行扫描,对索引列的数据进行排序,为索引分配存储空间,将索引的定义信息存储到数据字典中。创建后的索引完全由Oracle自动管理、维护和使用。例如,为SCOTT方案中的emp表创建基于sal的索引,代码如下所示:

create index idx_emp
on emp<sal>

即使在表中创建了索引,Oracle也不是机械的为该表上的所有查询都使用索引,而是根据查询的具体情况决定是否使用索引。在运行查询语句之前,Oracle一般需要对其进行优化。优化的目的是找到运行该查询语句的最佳途径。Oracle会使用两种优化器:RBO优化器(Rule Based Optimizer,基于规则的优化器)、CBO优化器(Cost Based Optimizer,基于开销的优化器)。优化器将使用全表扫描所需的资源开销与使用索引所需的资源开销进行对比,如果使用全表扫描的资源开销更节省,则不会使用索引。使用全表扫描所需的资源与表中的数据量大小密切相关。一般而言,当表中数据量达到一定数量时,优化器才会使用索引。
注意:为表创建过多的索引会降低更新、删除及插入的性能,因为Oracle还必须更新与该表关联的索引。

索引的分类
在Oracle中,索引可分为以下 5 种:
◇ 单列索引和复合索引
一个索引可以由一个或多个列组成,用于创建索引的列被称为“索引列”。单列索引时基于单个列所创建的索引,复合索引时基于两列或多列所创建的索引。
◇ 唯一索引与非唯一索引
唯一索引时索引列值不能重复的索引,非唯一索引是索引列值可以重复的索引,其索引列都允许取NULL值,默认情况下,Oracle创建的索引是非唯一索引。
◇ 标准(B-tree index,B树)索引
B树索引时Oracle中最常见的一种索引。在使用CREATE INDEX语句创建索引时,默认创建B树索引。B树索引可以是单列索引或复合索引、唯一索引或非唯一索引。B树索引按B树结构组织并存放索引。B树索引中的“B”是指“平衡”,该索引时一颗二叉树。
注意:B树索引能够适应多种查询条件,包括使用“=”的精确匹配、使用“LIKE”的模糊匹配,使用“>”或者“<”的比较条件。B树索引的局限性在于,当查询数据的范围超过表的10%后,就不能显现B树索引的良好性能。
◇ 位图索引
在讲解位图索引之前,需要首先引入基数的概念。基数是指某个列可能拥有的不重复值的个数。例如,Sex列的基数为2(性别只能是男或女),MaritalStatus列的基数为3(婚姻状况只能是未婚、已婚和离异)。对于一些基数很小的列,B树索引处理方式效率比较低。此时,为了加快查询效率,应当在这些列上创建位图索引,而非B树索引。
注意:当某个列的基数与表的总行数的比例少于1%时,建议在列上创建位图索引。另外,在表上创建一个单独的位图索引是无意义的。例如,如果只在Customer表的MaritalStatus列上创建一个位图索引,使用该位图索引进行查询时,将会返回大量的记录。因此,位图索引的作用来源于与其他位图索引的结合,例如在Region列上的位图索引,当在这两个列上查询时,Oracle就可以针对这两个列上的位图进行AND和OR等操作,以达到更好的效果。
◇ 函数索引
在Oracle中,不仅能够对表中的列创建索引,还可以对包含有列的函数或表达式创建索引。这种索引被称为函数索引。根据函数或表达式的结果的基数情况,函数索引既可以采用普通的B树索引,也可采用位图索引。例如,emp表中的hiredate列存储雇员的出生日期,如果需要搜索1980年以后出生的雇员信息,则使用的SQL语句如下:
select * from emp where extract(year from hiredate)>1980

虽然该语句能够正常运行,但即使在hiredate列创建过索引,Oracle也不会使用该索引,而是采用全表扫描。因为对该列值进行数据类转换后,该值不会存于索引中,所以Oracle被迫使用全表扫描。为了解决此类问题,可以使用函数索引。例如,创建如下的函数索引来解决此类问题:

CREATE INDEX funidx_extract_hiredate on emo(extract(year from hiredate))

创建后,Oracle就可以使用 funidx_extract_hiredate 索引来查询,从而提高查询效率。

创建各类索引
◇ 唯一索引
在emp表的ename列创建一个唯一索引idx_emp_ename,创建之后该表中的ename列就不允许出现重复值。
◇ 复合索引
如果SELECT语句中的WHERE子句引用了复合索引中的所有列或大多数列,则使用复合索引可以显著的提高查询效率。创建此类索引时,应该注意定义中使用的列的顺序。通常,最频繁访问的列应该放置在列表的最前面。创建复合索引的代码如下:
create index idx_emp_ename_job on(ename,job)

该代码语句对emp表中的ename列和job列创建了复合索引,当查询emp表示,如果WHERE条件类似于“WHERE name=‘JACK’ AND job=‘CLERK’”语句,则Oracle将会使用复合索引。
◇ 位图索引
在emp表中,job列、deptno列的取值范围有限,并且经常需要基于这些列进行查询、统计、汇总工作,所以应该基于这些列创建位图索引。创建位图索引的代码如下:

create bitmap index idx_bm_emp_job on emp(job)
创建索引的原则
并不是所有的表或者表中所有的列都需要创建索引,也不是在一张表上创建的索引越多越好,DBA应当只在适当的表或列上创建索引。创建索引应该遵循的一般原则包括以下9个方面:
⑴ 一般不需要为数据量很小的表创建索引。
⑵ 对于数据量比较大的表,如果经常需要查询的记录数大于表中所有的记录数的15%,则可以考虑为该表创建索引。此外,百分比不是绝对的,它只要取决于一次全表扫描的速度,全表扫描的速度越快,百分比越低。
⑶ 应该为大部分列值不重复的列创建索引。
⑷ 对于取值范围较大的列(如ename列),应该创建B树索引;对于取值范围较小的列(如Sex列),应该创建位图索引。
⑸ 对于包含很多NULL值,但经常需要查询所有非NULL值记录的列,应当创建索引。
⑹ 不能在LONG或BLOB等大对象数据类型的列上创建索引。
⑺ 对于经常需要连接(join)查询的多个表而言,在用于连接的列上创建索引能够显著提高查询的速度。
⑻ Oracle会自动的为具有PRIMARY KEY约束和UNIQUE约束的列创建索引,但是不会自动的为FOREIGN KEY列创建索引,所以用户需要为连接查询中使用的外键列创建索引。
⑼ 虽然一张表可以拥有任意数目的索引,但是表中的索引数目越多,维护索引的开销越大。向表中插入、更新或删除一条记录时,Oracle都必须对表的所有索引进行更新。因此,用户必须在表的查询速度和更新速度中找到一个合适的平衡点。如果在大部分情况下只需要对表执行只读操作,就可以为该表创建更多的索引以提高查询速度;如果在大部分情况下需要对表执行更新操作,则应减少创建一些索引,以提高更新速度。

猜你喜欢

转载自blog.csdn.net/My_ben/article/details/83006987