11GConcept第四章翻译Partitions,Views,andOtherSchemaObjects(分区,视图,以及其他SchemaObjects)
虽然表和索引是最重要、最常用的schema Objects,但是数据库还是很多其他schema objects。其中最常用的都在本章介绍。
本章包含下面几小节:
·Overview of Partitions(分区的概述)
·Overview of Views(视图的概述)
·Overview of Materialized Views(物化视图的概述)
·Overview of Sequences(sequences的介绍,一般翻作序列,感觉怪怪的,这里不翻)
·Overview of Dimensions(纬度表的概述,数据仓库里的东西)
·Overview of Synonyms(同义词的概述)
Overview of Partitions(分区的概述)
分区使你可以将超大表、索引拆分成 很多小的,可管理性更高的片段,这些片段就叫分区。
每个分区都是一个独立的对象,有它自己的名字和存储属性
举个生活案例来解释分区
假设人力资源经理有一个超大的盒子,这个盒子里面放着雇员的文件夹,每个文件夹有的对应雇员的雇佣日期。
现在经常有需求,要查询指定月份 雇佣了哪些人。有一个办法是创建一个索引在 雇员的雇佣日期上,将在盒子中分散存放的文件夹的位置 按顺序记录在上面。
相比较而言,分区策略就是使用很多小盒子,每个盒子存放指定月份雇佣的人的记录。
用小盒子有几个好处,当有人要问 六月份时雇佣人的文件夹时,人力资源经理可以直接在六月份 这个盒子里面找。更进一步来说,如果有任何的小盒子临时性的损坏了,其他小盒子这个时候依然可以正常使用。移动办公室的时候也容易了,由移动一个超重大盒子,变成移动 很多小盒子。
从应用的角度来看,还是只有一个大表存在。表分区以后,相关语句不需要进行修改。
分区适用于多种数据库应用类型,特别是那些管理者大量数据的.
分区的优点包括:
·Increase availability(增加了可用性)
一个分区的不可用,不会导致整个对象的不可用。查询优化器会自动在执行计划中移除相关分区,所以某些分区损坏了,对查询是不会有影响的.
·Easier administration of schema objects(简化了对象的管理)
一个分区后的对象,既可以整体的来管理,也可以针对某个分区来管理。
DDL语句可以只对某个分区进行操作,因此你可以将一些资源密集型的任务 拆开执行。比如重建索引或者重建表。
举个例子:你可以直接对表分区进行move。如果出现了什么问题,那么也只有这个分区需要重新move 而不是整个表。同样的,删除一个分区可以避免执行大量的DELETE语句。
·Reduced contention for shared resources inOLTP systems(OLTP系统中减少共享资源的争用)
在一些OLTP系统中,分区可以减少共享资源的争用
举个例子:DML操作分散在了多个segment中,而不是在一个segment。
·Enhanced query performance in datawarehouses(增强数据仓库的查询性能)
在数据仓库中,分区可以加速处理一些特殊查询
比如:一个有N百万条的销售记录表 可以分成四个分区。
Partition characteristics(分区有哪些特征)
表和索引的每个分区,必须拥有一样的 逻辑属性(attributes),比如列名,数据类型,约束等。
举个例子:一个表中的所有分区都公用同一种列、约束的定义,而索引的所有分区都公用相同的索引列。然而,每个分区都有自己独自的物理属性,比如 属于哪个表空间等。
Partitioning Key(分区key)
分区key 是一个或者多个列。用来决定分区表中的每一行应该去哪一个分区。
每一行只能属于 一个分区。
在sales表,你可以指定time_id列是range partition的key。数据库分配表中的行到哪个分区,这完全基于这行的time_id值是不是属于这个分区范围的。
Oracle数据库自动根据条件中的分区key来 直接对合适的分区进行DML。
Partitions Strategies(分区方案)
Oracle 提供了一些分区方案,用来决定数据该怎样进行分区。
基础的方案就是 range,list,hash分区.
Single-level(单级)分区策略,只使用这些数据分布方法的其中之一.
举例说明:要么只用range分区,要么只用list分区.
在Composite partitioning(组合分区)中,每个分区根据一种方法进行分区,然后每个分区又进一步分出子分区.
举例说明:你可以使用channel_id列进行list分区。然后再使用time_id进行range子分区
Range Partitioning(范围分区)
在范围分区中,数据库根据分区key 指定的范围 来决定行的归属。
范围分区最常用到date类型上。
假设你想在对表sales进行分区。sales行显示如下
你创建个分区表,名叫time_range_sales,看下面的语句。time_id列是分区key
CREATE TABLE time_range_sales
(prod_id NUMBER(6)
,cust_id NUMBER
,time_id DATE
,channel_id CHAR(1)
,promo_id NUMBER(6)
,quantity_sold NUMBER(3)
,amount_sold NUMBER(10,2)
)
PARTITION BY RANGE (time_id)
(PARTITION SALES_1998 VALUES LESS THAN(TO_DATE('01-JAN-1999','DD-MON-YYYY')),
PARTITION SALES_1999 VALUES LESS THAN(TO_DATE('01-JAN-2000','DD-MON-YYYY')),
PARTITION SALES_2000 VALUES LESS THAN(TO_DATE('01-JAN-2001','DD-MON-YYYY')),
PARTITION SALES_2001 VALUES LESS THAN (MAXVALUE)
);
之后,从之前sales表,将数据取出。加载到time_range_sales表。
数据库根据PARTITION BY RANGE指定的规则,对为每行选择合适的分区。
下图是行分布在四个分区的图:
Range 分区中,比分区可包含的最高值 再大一个值,这个值叫做transition point(过渡点,转接点等),像上图的SALES_1998分区包含的行,就是根据time_id列的值,小于transition point 01-JAN-1999.
数据库,在当有数据超过transition point时创建一个分区。当有数据属于分区时,分区的segment才会被创建。
上面的图中,如果数据大于或者等于01-JAN-2001时,那么这些数据讲会插入到 分区SALES_2001。(maxvalue)
List Partitoning(列表分区)
在列表分区中,数据库使用一个由不同具体值组成的列表作为每个分区的分区key。你可以使用列表分区控制不同的行进入不同的分区。当用来区分数据集的key不方便排序时,可以使用列表分区来分组和组织相关的数据集。
假设你使用下面语句创建了列表分区表list_sales。channel_id列就是这个分区表的分区key。
Example 4-3 List-Partitioned Table
CREATE TABLE list_sales
(prod_id NUMBER(6)
,cust_id NUMBER
,time_id DATE
, channel_id CHAR(1)
,promo_id NUMBER(6)
, quantity_sold NUMBER(3)
,amount_sold NUMBER(10,2)
)
PARTITION BY LIST (channel_id)
(PARTITION even_channels VALUES (2,4),
PARTITION odd_channels VALUES (3,9)
);
之后载入数据。下图显示了两个分区中数据的分布。数据库根据PARTITION BY LIST子句设置的规则,将每行根据其channel_id的值插入到相应的分区。
channel_id是2或者4的行,将存储到EVEN_CHANNELS分区。
channel_id是3或者9的行,将存储到ODD_CHANNELS分区。
Hash Partitioning(哈希分区)
在hash分区中,数据库根据 对指定的 分区键 进行hash运算后的值 创建分区。
每个行所处的位置 都由 指定列HASH后的值 所决定。
hash算法设计的目的,就是将行平均的分散到不同的分区。使得每个分区都能包含几乎相同数量的行。
Hash分区增强了表的可管理性,以前是管理一个超大表。现在可以对每个小部分进行单独管理。
一个HASH分区的丢失 不会影响到剩余的分区。而且这个分区可以单独被恢复。
Hash分区可以有效减少OLTP系统中的 更新争用
举个例子:通过将更新操作分散到 几个小segment 。
假设你使用了下列语句常见了hash_sales表,prod_id列是分区key。
CREATE TABLE hash_sales
(prod_id NUMBER(6)
,cust_id NUMBER
,time_id DATE
,channel_id CHAR(1)
,promo_id NUMBER(6)
,quantity_sold NUMBER(3)
,amount_sold NUMBER(10,2)
)
PARTITION BY HASH (prod_id)
PARTITIONS 2;
之后,加载进数据后,两个分区的数据分布可能如下,注意,这两个分区的名字是系统自动生成的:
你插入的行 ,数据库会努力将其 平均的,随机的分区到这些分区中。你无法指定 某行该插入哪个分区。数据库会执行hash函数,然后根据生成的值 决定该将这行放到哪个分区。
如果你改变了分区的数量(比如从2变成了3),这时数据库会对所有行进行重新分布,保证所有分区中都有基本相同数量的行。
Partitioned Tables(分区表)
一个分区表包括一个或多个分区。这些分区可以独立管理和操作。
一个表分为 分区表,非分区表。哪怕一个分区表 只包含一个分区,这个表也于非分区表不同.普通表没办法通过add命令增加分区.
一个分区表创建一个或多个segment.如果你创建一个名为hash_products的分区表,这时没有segment分配给它.直到分区中存入数据,这时候段才会被分配.每个分区segment包含一部分表的数据.
普通堆表的分区可以使用存储压缩特性..压缩可以节省空间以及加速查询速度.因此,压缩特性可以使用再数据仓库类似的环境(很少量的insert和update操作).
压缩特性可以定义在表空间,表,或者表分区级别.如果在表空间级别定义,则创建在这个表空间的表默认就是压缩的.你可以针对每个表进行修改这个特性,不过修改以后只对新插入的数据生效..一个表,或一个表分区 会同一时间既有压缩后的块,也有没压缩的块,它确保块不会因为压缩反而变大.如果压缩后的块反而变大,则数据库不会对这个块进行压缩.
Partitioned Indexes(分区索引)
分区索引,将一个索引拆分到多个可单独管理的部分.
Global indexes(全局索引):独立于分区表的定义进行分区。
Local indexes(局部索引):是自动根据表的分区定义进行索引。
和分区表一样,分区索引增强了 可管理型,可用性,性能以及扩展性。
下图显示了索引分区的可选项:
Local Partitioned Indexes(本地分区索引)
在本地分区索引,索引根据 分区表的 分区列 进行分区,相同的分区数量和相同的分区界限。索引分区与表分区相关联,这样存储在 索引分区中的key指向存储在一个表分区中的对应行。
在这种情况下,数据库会自动根据表分区中的数据 同步对应的索引分区,独立维护每个组合(一个表分区-一个索引分区)。
本地分区索引经常使用在数据仓库环境,本地分区索引有如下优势:
·可用性会增加。因为某个分区不可用只影响对应分区索引,对其他组合没有影响。
·维护起来更简单,当你move一个表分区,或者当一个分区中的数据删除,只有相对应的索引分区需要重建或者维护。如果是全局索引,则所有的索引分区必须都重建或维护。
·如果对一个表分区进行point-in-time recovery,则对应索引索引可以recover到对应的recover time。整个索引不需要进行重建。
hash_sales表根据prod_id进行hash分区,
下面语句对这个hash表的time_id列创建了一个本地索引。
CREATE INDEX hash_sales_idx ONhash_sales(time_id) LOCAL。
因为hash_sales表有两个分区,所以hash_sales_idx也有两个分区,每个索引分区关联不同的表分区。索引分区SYS_P38对表分区SYS_P33进行索引。而索引分区SYS_P39对表分区SYS_P34进行索引,如下图显示:
你没办法显式的增加一个索引分区。
一个索引分区的增加,只能是因为对应的分区表 增加了一个分区。
同样的,你也没办法显式的删除一个索引分区。
索引分区的删除,只能是因为对应分区表的 删除了一个分区
你也可以在分区表上创建bitmap索引。只有一个限制,那就是bitmap索引只能是本地索引。它不能是全局索引。全局bitmap索引只支持非分区表。
Local Prefixed andNonprefixed Indexes(前置索引或非前置索引)
本地分区索引分为以下类型:
·本地前置索引
这种类型,分区key包含在索引中,且在最前端。比如sales表根据time_id进行分区,一个本地前置索引在这个表,将会包含time_id列,且这个列在索引定义的最前列。
·本地非前置索引
这种类型,分区key没在索引的最前列,我们之前创建的hash_sales_idx这个索引,既是一个非前置索引,因为分区key product_id没有在索引中
这两种类型都可以 partition elimination(分区消除,也叫 partition pruning 分区剪裁),
当优化器访问数据时,认为有一些分区可以排除,则分区消除发生。一个查询可消除的分区取决于谓词(where).当一个查询使用前置索引时,则索引分区消除总是会发生.而使用非前置索引时,则可能不会(基本上不会).
Local Partitioned IndexStorage(本地分区索引的存储)
和表分区一样,本地索引分区存到自己独有的segment中,每个segment包含整个索引数据的一部分,一个本地索引,有四个索引分区,是分别存放在四个独立的segment中。
Global Partitioned Indexes(全局分区索引)
全局分区索引是一个独立于底层表的分区索引。一个索引分区可以指向任何一个,多个,甚至全部的表分区。而在本地分区索引中,索引分区和表分区是一一对应的。
正常情况,全局分区索引适用于OLTP应用(重点需要快速访问,数据完整,以及可用性)。
在一个OLTP系统中,一个表可能只根据一个key进行分区,举个例子,像employees.department_id列。但是应用可能需要通过不同的keys进行数据访问,举个例子,像通过employee_id或者job_id。全局分区索引适用于这种情况。
你可以讲一个全局索引根据range或者hash进行分区。如果根据range分区,那么数据库将全局索引根据你指定的 列 的相应区间值 进行分区。如果根据hash进行分区,则数据库根据指定 行中列值根据hash函数hash出来的值,存储到相应分区。
举个例子:假设你创建了一个global 分区索引 在time_range_sales(上面根据年份创建的那个例子)表。在这种情况下,1998年的销售记录都存在一个分区,而1999年
的销售记录在另外一个分区,以此类推。
下面创建了一个根据channel_id列的全局分区索引。
CREATE INDEX time_channel_sales_idx ONtime_range_sales(channel_id)
GLOBAL PARTITION BY RANGE(channel_id)
(PARTITION p1 VALUES LESS THAN(3),
PARTITIONP2 VALUES LESS THAN(4),
PARTITIONP3 VALUES LESS THAN(MAXVALUE));
如下图显示,一个全局索引分区可以包含指向多个表分区的条目。索引分区p1指向行是channel_id等于2的。索引分区p2指向的行是channel_id等于3的,以及索引分区p3指向的行是channel_id从4到9的。可以通过查询*_part_indexes来确认索引是local分区还是global分区。
Partitioned Index-OrganizedTables(IOT分区)
IOT表,可以进行range,list,HASH分区。
分区提供了更高的可管理型,可用性和性能
另外,使用IOT的数据墨盒也可以利用这个功能来分区存储它的数据。
在IOT中使用分区需注意:
·分区列必须是主键列,或者主键列的一部分。
·可以在上面创建另外的索引(全局,本地)
·OVERFLOW数据库段的数量 永远和表分区的数量相等。
Oracle数据库支持bitmap索引创建在分区或者不分区的IOT上。在IOT表创建bitmap后,mapping表会自动创建。
Overview of Views(视图概述)
一个view(视图)是一个表或者多个表逻辑的呈现。实际上,view就是一个存储好的查询语句.一个视图基于一些表创建,而这些表叫做base tables(基表,听起来很基吧)
基表可以是表,也可以是其他的视图.
所有对于视图的操作,实际上是对下面的基表进行处理.
在可以用表的地方,视图都可以用.
提示:Materialized views(物化视图)和普通的视图完全不一样,后面会说到.
视图可以使你针对不同的用户,显示相同数据的不同部分.视图经常被用来:
·通过限制表中特定行,或者特定列的显示,来增加安全性
随后的图 会显示staff视图不显示基表employees的salary或commission_pct列.
·隐藏数据的复杂性
举个例子,一个视图可以是一个join语句,这个语句多个表中相关字段,行的组合.
视图隐藏了实际情况,一大串语句使用一个视图名就代替了.
一个查询同样可能根据表的信息进行大量的计算.
用户可以通过查询一个视图来获取这些信息,而不需要去知道这些join或计算本身如何操作的.
·通过不同的视角看基表的数据
举个例子:在视图中,可以对基表的列进行改名,而不会影响到基表(列别名)
·隔绝基表的定义变化
举个例子:一个视图是查询基表中三个列(基表本身有四列),现在基表增加了一个列,变成了五列。这时视图的定义是不会发生任何改变的。而使用视图的应用也不会有任何影响。
举个使用视图的例子。hr.employees表,它有一些列,还有很多行。为了使用户只能 这些列中的5列。这时 你可以创建一个视图:
CREATE VIEW staff AS
SELECT employee_id,last_name,job_id,manager_id,department_id
FROMemployees;
和所有的子查询一样,视图中的查询语句不能包含 FOR UPDATE子句。
下图描述了staff视图,注意这个视图只显示了基表中的五个列。
Characteristics of Views(视图的特征)
和表不一样,一个视图是不需要分配存储空间的(没segment),视图本身是没数据的。
视图是定义在数据字典中的一个语句。
视图和它引用的对象 之间 存在 依赖关系,这个依赖关系由数据库自己处理
举个例子,如果你删除以及重新创建了视图相关的一个基表,则数据库会判断这个新的基表对于视图的定义来说 是否可以接受。
Data Manipulation in Views(对于视图的数据操作)
视图和表有很多相似的地方。举个栗子。一个视图可以有最多1000列,和表一样。
用户可以查询视图。在一些限制下,用户也可以对视图进行DML操作。
对视图进行操作,其实影响的数据是视图基表的,受限于基表的完整性约束,以及会触发基表的触发器。
下面创建了一个视图:
CREATE VIEW staff_dept_10 AS
SELECT employee_id,last_name,job_id,
manager_id,department_id
FROM employees
WHERE department_id=10
WITH CHECK OPTION CONSTRANTstaff_dept_10_cnst;
这个查询只应用了department=10的行,CHECK OPTION子句建了一个约束,保证对视图执行INSERT ,UPDATE后的结果,一定要可以从视图中SELECT,否则则该DML不允许执行。
因此,department_id列值是10的行,可以插入这个视图,但是30是的行是不允许插入的。
How Data Is Accessed inViews(视图中数据是如何访问的)
Oracle数据库在数据字典中存储视图的定义(查询语句),当你在sql中使用了视图,Oracle数据库会执行下面的操作:
1、对查询这个视图的语句,进行合并查询,将查询 视图,变成查询视图各个基表。
Oracle 合并查询,就是你这个查询虽然使用了视图,但是好像你没有使用似的
因此,数据库就可以使用基表上任意一列的索引,无论这个一列是不是在这个视图的定义中。
有些时候,Oracle数据库没办法在用户查询的时候 没有办法对视图合并,在这些情况下,数据库可能没办法使用基表所有列上的索引。
2、将合并后的语句进行解析,然后放入shared sql area
Oracle数据库将这个SQL解析,放入shared sql area,因此使用了视图节省了内存的使用(相关语句变短了)。
3、执行这个SQL。
下面这个语句解析了数据库访问的过程。假设你创建了employees_view的视图,这个视图基于employees和departments表:
CREATE VIEW employees_view AS
SELECT employee_id,last_name,salary,location_id
FROMemployees JOIN departments USING(department_id)
WHEREdepartments.department_id=10;
一个用户执行了如下查询:
SELECT last_name
FROM employees_view
WHERE employee_id=9876;
Oracle数据库会将视图合并,成为如下结构的查询语句,这个语句是它真正获取数据的语句:
SELECT last_name
FROM employees,departments
WHEREemployees.department_id=departments.department_id
AND departments.department_id=10
AND employees.employee_id=9876;
Updatable Join Views(可更新的join视图)
Join视图就是 该视图定义时,FROM后面有多个表 或者视图。
下面的例子中,staff_depat_10_30视图就是根据employees和departments表join的。
仅仅包括department_id是10和30的雇员信息。
CREATE VIEW staff_dept_10_30 AS
SELECTemployee_id,last_name,job_id,e.department_id
FROM employees e,departments d
WHERE e.department_id IN (10,30)
AND e.department_id = d.department_id;
一个可更新的join视图,可以同样可以叫modifiable join view(可修改的视图),涉及两个或者多个基表的视图,而且可以执行DML操作。
可更新join视图包括多个表在第一层FROM后面,而且没有WITH READ ONLY约束子句。
为了实现真正意义上的可更新,一个视图必须满足几个条件。
举个例子,一个最基本的规则就是,一个INSERT,UPDATE或者DELETE操作,在一个join视图上,同一时间只能对其中的一个基表进行操作。
下面查询USER_UPDATABLE_COLUMNS数据字典的语句,显示出这个视图是可以更新的:
SQL> SELECT TABLE_NAME, COLUMN_NAME,UPDATABLE
2 FROM USER_UPDATABLE_COLUMNS
3 WHERE TABLE_NAME = 'STAFF_DEPT_10_30';
一个join 视图上,所有可更新的列,都必须映射向一个key-preserved table(键保护的表),
在join查询中,一个键保护的表指的是,每个基表中的行,在查询视图时 最多出现一次。
在上面创建视图的例子中,department_id是departments表的主键,这样employees表的每行与departments join后,只出现一次,这里使得employees表 成为键保护的表。
在这里departments表是非键保护的表。因为它的每一行可能会很多次的出现在返回的结果中。
Object Views
像view是一个虚拟表一样,一个object view也是一个虚拟的object 表。view中的每行都是一个object(实体)。object是object type(抽象的现实世界实体,比如采购订单)的一个具体案例。object type是用户自定义的数据类型。
你可以检索,更新,插入以及删除 相关数据,如果它们是存放成一个object。你同样可以使用object type定义为视图中的一列,想嵌套表或者数组那样。
和普通事务一样,object 视图可以只提供你想让用户看见的数据。
举个例子,一个object 视图可以提供关于IT程序猿的数据,但是隐藏了敏感数据 比如工资。
下面的例子是创建了一个employee_type Object然后视图it_prog_view基于这个object:
CREATE TYPE employee_type AS OBJECT
(employee_id NUMBER(6),
last_name VARCHAR2(25),
job_id VARCHAR2(10)
);
/
CREATE VIEW it_prog_view OF employee_type
WITHOBJECT IDENTIFIER (employee_id) AS
SELECT e.employee_id, e.last_name, e.job_id
FROM employees e
WHERE job_id = 'IT_PROG';
Object视图在原型程序或者面向对象转换的应用中非常有用。因为view中的数据可以通过下面的关系型表获取。你可以正常运行面向对象的应用,而不需要转换原本存在的表到不同的物理结构。
Overview of MaterializedViews(物化视图概述)
物化视图,查询的结果 事先被存储好了。查询中的FROM语句可以是表,视图,物化视图,这些对象的集合 叫做对象统称为master table(主表,复制术语)或者 detail tables(明细表,数据仓库术语)。
物化视图用来汇总,计算,负责,分散数据。它适用于多重计算环境,它适用于如下各种计算环境:
·在数据仓库环境,你可以使用物化视图计算以及存储分组函数计算出来的值,比如像sum或avg。
一个summary就是一个聚合的视图,通过预先的计算和聚合,并将结果存入一个表中,用来减少查询时间。
物化视图就相当于 summary(看"Data WarehouseArchitecture(Basic)").你同样可以使用物化视图来计算和聚合(可不聚合),如果兼容性是Oracle 9i或以上,那么物化视图可以用在加where的查询语句。
·在物化视图复制中,视图保存 表 某一个时间 全部或者部分的 数据copy。物化视图将数据分发到几个节点,同步各个节点的更新。这种形式的 复制 适合的环境 如现场销售人员,手中的数据库无法保证试试连接着网络。
·在移动的计算环境中,你可以使用物化视图 从 服务器上下载数据子集到移动客户端上,定期从中心服务器刷新最新数据,并定期讲客户端的修改传回中心服务器。
在一个复制环境中,一个物化视图分享其他数据库的表中的数据,这个数据库叫做master database。物化视图关联的原始表叫做master table
下图图解 一个数据库中的物化视图(数据基于其他数据库),master table的更新操作将复制到物化视图数据库。Characteristics ofMaterialized Views(物化视图的特性)
物化视图与普通视图和索引具有某些共同的特性。
物化视图在以下几方面与索引类似:
·都拥有真正的数据,消耗存储
·当master表数据更改时,它们的数据都会随之刷新
·当用于查询重写操作时,它们都可以提升sql的执行性能
·它们的存在对于SQL应用和用户来说是透明的。
物化视图和视图相似的地方是,它显示的数据是其他表或者视图中的,用户可以直接使用SELECT语句来查询物化视图。取决于所需要的刷新类型,物化视图也可以使用DML语句进行更新。
下面的例子创建和填充了一个物化视图,基于的sh用户的三个master tables:
CREATE MATERIALIZED VIEW sales_mv AS
SELECT t.calendar_year, p.prod_id, SUM(s.amount_sold) AS sum_sales
FROM times t, products p, saless
WHERE t.time_id = s.time_id
AND p.prod_id = s.prod_id
GROUPBY t.calendar_year, p.prod_id;
下面的示例删除了sales表,这个表是sales_mv的master 表之一,然后查询sales_mv.
可以查询出数据,因为在物化视图中的数据和master表中的数据是单独存放的.
SQL> DROP TABLE sales;
Table dropped.
SQL> SELECT * FROM sales_mv WHERE ROWNUM< 4;
CALENDAR_YEAR PROD_ID SUM_SALES
------------- ---------- ----------
1998 13 936197.53
1998 26 567533.83
1998 27 107968.24
物化视图可以分区.你可以定义一个物化视图在一个分区表上.以及在物化视图上创建一到多个索引
Refresh Methods forMateralized Views(物化视图的刷新方法)
数据库维护物化视图中数据的方法,就是在master表数据变化以后,将变化刷新到物化视图中.
刷新方法是可以增量的,叫做fast refresh.或者是complete refresh(完整刷新)。
当物化视图初始化且子句是BUILD IMMEDIATE时,会发生complete refresh。除非物化视图引用了预先创建好的表。刷新涉及到执行物化视图定义中的查询。这个处理过程可能很慢,尤其是数据库必须读出和处理大量的数据。
fast refresh消除了从零开始重建物化视图的必要。因此,它仅处理发生的变化,这样非常快的刷新完成。
物化视图可以根据需要或者定时刷新。此外,和master表在同一个数据库中的物化视图,可以在相关基表 事务提交时进行刷新。
为了物化视图可以使用fast refresh 方法。materialized view log或着direct loader log记录了主表的变化。一个materialized view log是一个schema object ,它记录了master表的数据更改,通过它 物化视图可以增量的刷新。每个materialized view log 和一个master表进行关联。materialized view log创建在master table所在的数据库中,所在的schema中。
Query Rewrite(查询重写)
查询重写是一种优化技术,它把用户的对master tables的写请求,转换成意思相同,但包含了对相关物化视图的修改写请求。
当基表包含大量的数据,运算聚集函数或者join是非常昂贵且耗时的。因为物化视图包含的数据是已经计算好的,查询重写可以快速的使用物化视图 对请求进行响应。
CBO查询重写是透明的,无需用户介入,SQL语句中也不需要应用物化视图。
因为查询重写是透明的,物化视图的添加和删除,不会使应用代码中的SQL语句失效。
通常,重写的查询会用物化视图,而不是表,这样减少了响应时间
下图显示了数据库 原始和经过重现的执行计划,然后选择成本最低的执行计划
Overview of Sequences(序列的概述)
序列是一个schema object,多个用户可以使用一个序列来产生唯一的整数。
一个序列提供了很好的灵活性以及不错的执行方法 用来产生 一个数值类型的替代主键。
Sequence Characteristics(序列的特征)
一个序列的创建需要提供以下信息:
·序列的名字
·序列是升序还是降序
·每次间隔多大
·数据库是否需要将一部分sequence产生的值 cache到内存中。
·当序列的限制达到时,是否循环
下面的案例创建一个名叫customers_seq的序列。在oe用户下。
一个应用打算使用这个序列来产生雇员编号。
CREATE SEQUENCE customers_seq
START WITH 1000
INCREMENT BY 1
NOCACHE
NOCYCLE;
第一次引用customers_seq.nextval 将返回1000,第二次将返回1001. 每一次引用都比上一次的值大1
Concurrent Access to Sequences(并发访问序列)
一个序列可以为几个不同的表产生数字.这种情况下,数据库可以自动产生主键,以及协调这些跨越了行或者表的键.举个例子:一个序列可以给orders表和customers表产生主键.
多用户环境中,为了产生唯一数字,而且不增加磁盘开销,这时序列是有用的。
举个例子,两个用户同时插入新行到orders表。
通过使用序列来产生order_id列的唯一值,任何一个用户都不需要等待别人输入下一个值。序列会自动产生正确的值,给每个用户。
每个引用序列的用户 都可以访问他或她的当前序列号,这个序列号就是本会话产生的最后一个序列号。一个用户可以使用一个语句来产生新的序列号或者使用当前系列号(本会话最后产生的序列号)
在一个会话中使用语句产生序列号,这个序列号只在这个会话可用。
个别序列号可能会发生跳过现象,这是因为一个事务产生和使用了这个序列号,这个事务最终又回滚掉了。
警告:如果你的应用需要没有间隙的一组数字,那么你不能使用Oracle序列。你必须自己开发代码来实现这连续的行为。
Overview of Dimensions(维度概述)
一个标准的数据仓库有两个重要的组建,维度表和事实表。
一个维度表用于阐述业务问题的类别
举个例子:时间,地理,产品,部门,以及分销渠道
一个事实表 是一组指定的维度的值 相关联的 事件或者实体
举个例子:销售数量或者利润。
多维度需求的例子包括如下:
·以上升聚合方式,在2007到2008年间,在地理维度上从州上升到国家到全球,跨越所有产品的销售额。
·创建一个跨表格的分析。关于2007-2008年间 在南美运营情况,包括所有的可汇总的
·根据 2008年汽车产品销售收入,列出在亚洲的前 10位销售代表,并按其佣金分级。
很多 多维度问题 经常需要跨时间,地区或者预算 来汇聚数据以及比较数据集
创建一个维可以使查询重写特性更广泛的使用,在透明的重写查询去使用物化视图后,数据库可以提升查询性能。
Hierarchical Structure of aDimension(维度的层次结构)
一个维度表是一个逻辑结构,它定义了两列或者多列之间的体系关系。维度没有分配存储。
维度信息是存在维度表中的,而事实信息也是存在事实表中的。
在 用户维度,用户向上存,从城市,省,国家,州,全球。数据分析 正常情况是在高级别的维度层次 根据情况需要逐步深入。
在子级别的每个值 都和一个父级别的值进行关联。一个层次关系是一个层次 到另一个层次的 功能性依赖。
Creation of Dimensions(维度的创建)
维度是通过sql语句创建的,CREATE DIMENSION 语句指定了如下:
·多个LEVEL 子句,每个表示了维度中的一列,或者一组列
·一个或多个HIERARCHY子句 指定了父子关系
·可选的ATTRIBUTE子句,每个表示个别级别 附加的列或一组列。
下面语句是就创建customers_dim维度的语句:
CREATE DIMENSION customers_dim
LEVELcustomer IS (customers.cust_id)
LEVELcity IS (customers.cust_city)
LEVELstate IS(customers.cust_state_province)
LEVELcountry IS (countries.country_id)
LEVELsubregion IS (countries.country_subregion)
LEVELregion IS (countries.country_region)
HIERARCHY geog_rollup (
customer CHILD OF
city CHILD OF
state CHILD OF
country CHILD OF
subregion CHILD OF
region
JOIN KEY (customers.country_id) REFERENCES country)
ATTRIBUTE customer DETERMINES
(cust_first_name,cust_last_name,cust_gender,
cust_marital_status,cust_year_of_birth,
cust_income_level,cust_credit_limit)
ATTRIBUTE country DETERMINES(countries.country_name);
一个维度中的列可以在 同一个表中(反规范化) 或者从多个表中(完全或者部分规范化)
举个例子。一个规范化的时间维度可以包含 一个日期表,一个月表,一个年表,通过使用join条件将每个日期行与月行关联,每个月行与年行关联。
而在完全反规范化的时间维度中,日期,月,年列都在同一个表中,无论是规范化或者反规划反,列之间的层次关系必须在CREATE DIMENSION 语句中指定。
Overview of Synonyms(同义词概述)
一个同义词就是一个schema object的别名。举个例子,你可以创建同义词 给表、视图、序列、PL/SQL 程序单元、用户定义的对象类型、或者别的同义词。
因为同义词就是一个简单的别名。它不需要存储,它就是数据字典中的一条定义。
同义词可以简化SQL语句。同义词同样对隐藏基础对象的位置有用。
如果基础对象必须要重命名或者更改位置,那么只需要对同义词进行重定义,而应用基于同义词的SQL可以继续工作,不需要进行调整。
你可以创建private(私有)和public(公共) 两种同义词。
private同义词是在指定用户的schema中,用户可以控制它对谁生效。
public同义词是被用户组PUBLIC所拥有,它对每个数据库用户生效。
下面例子中,DBA给hr.employees表创建了一个叫people的全局同义词
oe用户通过people同义词来计算 employees表中的行数。
SQL>CREATE PUBLIC SYNONYM people FORhr.employees;
Synonym created.
SQL> CONNECT oe/oe
Connected.
SQL>SELECT COUNT(*) FROM people;
COUNT(*)
----------
107
使用公共同义词很少,因为他们使得数据库整合更加困难
像下面的案例,如果其他管理员打算创建公共同义词people。那么将会保存,因为一个数据库中只有一个公共同义词people可以存在。公共同义词的滥用会导致多个应用之间的命名空间冲突。
SQL> CREATE PUBLIC SYNONYM people FORoe.customers;
CREATE PUBLIC SYNONYM people FOR oe.customers
*
ERROR at line 1:
ORA-00955: name is already used by anexisting object
SQL> SELECT OWNER, SYNONYM_NAME,TABLE_OWNER, TABLE_NAME
2 FROM DBA_SYNONYMS
3 WHERE SYNONYM_NAME = 'PEOPLE';
OWNER SYNONYM_NAME TABLE_OWNER TABLE_NAME
---------- ------------ ---------------------
PUBLIC PEOPLE HR EMPLOYEES
同义词自身是不安全的,当你授予统一的对象权限时,你应该已经授权基础对象的权限。同义词在grant语句中,只作为对象的别名。
- 01-11全球最受赞誉公司揭晓:苹果连续九年第一
- 12-09罗伯特·莫里斯:让黑客真正变黑
- 12-09谁闯入了中国网络?揭秘美国绝密黑客小组TA
- 12-09警示:iOS6 惊现“闪退”BUG