Oracle9i 实体化视图 执行概要 今天的数据库,无论是数据仓库、数据中心还是OLTP 系统,都包含大量的信息等待人们去发现和理解。然而,如何以一种及时的方式查找和表示这些信息是一个重大的问题,尤其是当需要搜索庞大数量信息的时候。
实体化视图能够帮助解决这个问题,因为它提供了一种快速访问和报告数据的方法。 简介 实体化视图首先在Oracle8i 中引入,是称为“概要治理”的组件的一部分。可能您的公司已经在使用实体化视图,但只知道它的其他名字,例如概要或聚合表。在这里我们讨论如何创建和治理实体化视图,还讨论查询重写功能如何透明地重写SQL 查询,从而使用实体化视图来缩短查询响应时间。这将使数据库用户完全无需知道存在哪些实体化视图。 实体化视图应看作是一种非凡的视图,它物理上存在于数据库内部,可以包括联接和/或聚合。它能够在执行之前预先计算开销大的联接和聚合操作,因此它的存在缩短了查询执行时间。 今天,使用自身概要的公司花费了大量的时间用于手工创建概要、识别将创建哪些概要、对概要进行索引和更新,以及建议用户使用哪些概要。 现在DBA 将仅须在开始时创建实体化视图,而无论数据源何时发生变化,它都将被自动更新。此外还有一个概要顾问组件,它向DBA 推荐创建、删除和保留哪些实体化视图。 数据仓库或数据库用户将可以体会到使用实体化视图的最大好处之一,DBA 无须再告诉他们存在哪些实体化视图。他们可以对数据库中的表或视图编写自己的查询。然后Oracle 服务器的查询重写机制将自动重写SQL 查询以使用实体化视图。这样就大大缩短了查询响应时间,终端用户无须“了解概要”。 为何使用概要治理 当向数据仓库终端用户问起他们希望从中获得什么,大部分人都会回答:快速准确的信息。但是这也给数据仓库设计者出了个大难题:为了回答“在y 地点我们卖出多少件x 产品”,同时希望避免读取表中的每一行,必须建立一条到数据的快速路由。 解决此问题最常见的办法之一就是创建概要表,Oracle 将其称为实体化视图。这一工作包括首先要理解典型负荷,然后创建规模非常小的实体化视图,实体化视图中可以包含所需信息的联接和/或聚合。例如,为了回答前面的问题,实体化视图中每种产品对应于一行,指明每个区域的销售量。因此假如一家公司在5 个地点销售2000 件产品,则将要读取的最大行数始终为10000,而无论已经售出多少商品。 很明显,实体化视图必须保证精确,但该技术意味着终端用户现在需要读取的行数很少,因此可以始终快速地接收结果。数据库容量已经增长到兆兆字节,因此使用这样的方法来缩短查询响应时间就显得越来越重要。今天许多站点都创建了自己的概要表,因此使用Oracle8 概要治理所带来的额外好处是: 1、Oracle 中的查询重写机制是透明的并采用实体化视图(即使它仅能部分满足查询的需要)。 2、具有高级的查询重写,可以使用实体化视图对不同聚合级别(例如按照星期、月和年)进行报告。 3、自动化机制刷新实体化视图,单个请求刷新所有实体化视图。 4、DBA 不再需要花时间查找应创建哪些实体化视图。系统将基于过去对数据库或数据仓库的查询,向DBA 提供有关需要哪些概要的信息。 概要治理组件 组成概要治理的有五个组件: 1、维度 2、实体化视图 3、刷新 4、查询重写 5、概要顾问 并不需要使用所有组件,但所选用的组件越多,获得的优势就越多。现在我们将具体探讨这些组件。 模式需求 用于实体化视图的模式类型或设计没有什么限制。因此在数据仓库环境中,模式可以是雪花式的设计,但这并不是必须的。 对于熟悉产品系统中数据库设计技术的设计者来说,在一个数据仓库中必须使用不同的规则和技术。例如,产品数据库通常是规范化的,因此在这种情况下,时间维的表示方法最好是采用三个表:日、月、年。联接条件应该满足:将每个日期行连接到一个(仅一个)月份行,每个月份行连接到一个(仅一个)年份行。数据仓库实现通常将导致一个完全非规范化的的时间维表,其中日期、月份、年份栏都处于同一个表中。不过,无论设计使用的是规范化还是非规范化表,都可以使用实体化视图。 维度 在创建一个实体化视图之前,第一步应该是回顾模式,指明维度。维度定义了列之间的层次化(父级/子级)关系,所有的列无须来自同一个表。我们强烈推荐定义数据的维度,因为这将有助于查询重写和概要顾问做出更佳决策。 数据库设计者所面临的另一个问题是,频繁查询将不会直接涉及所有的维度列,而仅参考与维度相关的那一列,例如查询仅参考星期二而不是具体日期。因此当定义了维度之后,还必须描述维度列和表中其它列之间的关系。 图1 显示了包含两个层次的时间维。从一个指定日期开始,有一个层次告诉我们该日期涉及哪些财政周、月或年,而另一个层次定义了日、月、季度和年之间的关系。 当定义了一个层次之后,可以指定多个列来描述该层次,例如,假如City 在每个State 之内是唯一的,但是在States 之间不唯一,那么就需要指定一个地理层次,其形式如(Country State,
按照图1 画出维度,可以帮助DBA 完成定义过程。每个圆圈代表维度中的一个级别过LEVEL 子句来声明。维层次通过HERARCHY 子句来声明。概要治理也同样依靠于DBA 定义约束条件,保证层次级别中每一级别的列非空。 在图2 中,我们可以看到创建该维度的SQL 语句。级别名称对应于维表中的列。然后使用这些级别名称来描述每一层次。最后,使用ATTRIBUTE 子句来定义具有直接关系的项目。因此属性calendar_month_name 与级别month 有关系。 使用JOIN KEY 子句来声明维度中的1:n 联接关系。在事实表和维表之间,使用事实表中的FOREIGN KEY 和NOT NULL 约束条件来表示这种联接关系。 定义维度的相关提示 为帮助创建维度,请按照下面的简单步骤: 1. 指明模式中的所有维度和维表。假如维度是规范化的,即它存储在多个表中,那么请检查维表之间的联接,确保每个子级行联接到一个(仅一个)父级行。对于非规范化维度,请检查子级列是否唯一确定父级(或属性)列。假如不遵守这些规则,可能会在查询时得到错误的结果。 2. 指明每一维度中的层次。例如,day 是month 的子级(我们可以将day 级别聚合到month),quarter 是year 的子级。 3. 指明层次中每一级别的属性依靠关系。例如,指明calendar_month_name 是month 的属性。 4. 指明数据仓库中每个事实表到维度之间的联接,检查每个联接,确保每个事实行联接到一个(仅一个)维度行。必须声明该条件,而且还可以选择是否强制执行该条件,其方法是向事实要害列添加FOREIGN KEY 和NOT NULL 约束条件,向父级联接键添加PRIMARY KEY 约束条件。可以通过NOVALIDATE 选项来启用这些约束条件,从而无须花费时间来验证表中的每一行是否满足这些约束条件。对于所有未得到验证的约束条件,还需要新的RELY 子句来使其能够用于查询重写中。 图2 创建时间维的SQL 语句 CREATE DIMENSION times_dim LEVEL day IS TIMES.TIME_ID LEVEL month IS TIMES.CALENDAR_MONTH_DESC LEVEL quarter IS TIMES.CALENDAR_QUARTER_DESC LEVEL year IS TIMES.CALENDAR_YEAR LEVEL fis_week IS TIMES.WEEK_ENDING_DAY LEVEL fis_month IS TIMES.FISCAL_MONTH_DESC LEVEL fis_quarter IS TIMES.FISCAL_QUARTER_DESC LEVEL fis_year IS TIMES.FISCAL_YEAR HIERARCHY cal_rollup ( day CHILD OF month CHILD OF quarter CHILD OF year ) HIERARCHY fis_rollup ( day CHILD OF fis_week CHILD OF fis_month CHILD OF fis_quarter CHILD OF fis_year ) ATTRIBUTE day DETERMINES (day_number_in_week, day_name, day_number_in_month, calendar_week_number) ATTRIBUTE month DETERMINES (calendar_month_desc, calendar_month_number, calendar_month_name, days_in_cal_month, end_of_cal_month) ATTRIBUTE quarter DETERMINES (calendar_quarter_desc,calendar_quarter_number, days_in_cal_quarter, end_of_cal_quarter) ATTRIBUTE year DETERMINES (calendar_year, days_in_cal_year, end_of_cal_year) ATTRIBUTE fis_week DETERMINES (week_ending_day, fiscal_week_number) ; 实体化视图 一旦定义了维度,就可以创建实体化视图。现在我们将着重介绍什么是实体化视图,在后面我们将看到建议功能如何推荐创建哪些实体化视图。 实体化视图定义可包括聚合,例如SUM MIN、MAX、AVG、COUNT(*)、COUNT(x)、COUNT(DISTINCT)、VARIANCE 或STDDEV, 还可以包括一个或多个联接到一起的表和一个GROUP BY。可以进行索引和分区,还可以应用基本的DLL 操作,例如CREATE、ALTER 和DROP。 由于实体化视图是数据库中的一个对象,因此在很多方面它更像一个索引,因为 实体化视图的目的是提高查询执行性能。 实体化视图的存在对于SQL 应用程序是透明的,因