Oracle 学习之 数据仓库(二) Dimension 的理解

在数据仓库中,有事实表、维度表两个概念。

事实表是数据仓库结构中的中央表,它包含联系事实与维度表的数字度量值和键。事实数据表包含描述业务(例如产品销售)内特定事件的数据。

维度表是维度属性的集合。是分析问题的一个窗口。是人们观察数据的特定角度,是考虑问题时的一类属性,属性的集合构成一个维。

如图示

我们以sh用户下的sales表和times表来看,

SALES为事实表

SQL> desc sales
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 PROD_ID				   NOT NULL NUMBER
 CUST_ID				   NOT NULL NUMBER
 TIME_ID				   NOT NULL DATE
 CHANNEL_ID				   NOT NULL NUMBER
 PROMO_ID				   NOT NULL NUMBER
 QUANTITY_SOLD				   NOT NULL NUMBER(10,2)
 AMOUNT_SOLD				   NOT NULL NUMBER(10,2)

TIMES为维度表

SQL> desc times
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 TIME_ID				   NOT NULL DATE
 DAY_NAME				   NOT NULL VARCHAR2(9)
 DAY_NUMBER_IN_WEEK			   NOT NULL NUMBER(1)
 DAY_NUMBER_IN_MONTH			   NOT NULL NUMBER(2)
 CALENDAR_WEEK_NUMBER			   NOT NULL NUMBER(2)
 FISCAL_WEEK_NUMBER			   NOT NULL NUMBER(2)
 WEEK_ENDING_DAY			   NOT NULL DATE
 WEEK_ENDING_DAY_ID			   NOT NULL NUMBER
 CALENDAR_MONTH_NUMBER			   NOT NULL NUMBER(2)
 FISCAL_MONTH_NUMBER			   NOT NULL NUMBER(2)
 CALENDAR_MONTH_DESC			   NOT NULL VARCHAR2(8)
 CALENDAR_MONTH_ID			   NOT NULL NUMBER
 FISCAL_MONTH_DESC			   NOT NULL VARCHAR2(8)
 FISCAL_MONTH_ID			   NOT NULL NUMBER
 DAYS_IN_CAL_MONTH			   NOT NULL NUMBER
 DAYS_IN_FIS_MONTH			   NOT NULL NUMBER
 END_OF_CAL_MONTH			   NOT NULL DATE
 END_OF_FIS_MONTH			   NOT NULL DATE
 CALENDAR_MONTH_NAME			   NOT NULL VARCHAR2(9)
 FISCAL_MONTH_NAME			   NOT NULL VARCHAR2(9)
 CALENDAR_QUARTER_DESC			   NOT NULL CHAR(7)
 CALENDAR_QUARTER_ID			   NOT NULL NUMBER
 FISCAL_QUARTER_DESC			   NOT NULL CHAR(7)
 FISCAL_QUARTER_ID			   NOT NULL NUMBER
 DAYS_IN_CAL_QUARTER			   NOT NULL NUMBER
 DAYS_IN_FIS_QUARTER			   NOT NULL NUMBER
 END_OF_CAL_QUARTER			   NOT NULL DATE
 END_OF_FIS_QUARTER			   NOT NULL DATE
 CALENDAR_QUARTER_NUMBER		   NOT NULL NUMBER(1)
 FISCAL_QUARTER_NUMBER			   NOT NULL NUMBER(1)
 CALENDAR_YEAR				   NOT NULL NUMBER(4)
 CALENDAR_YEAR_ID			   NOT NULL NUMBER
 FISCAL_YEAR				   NOT NULL NUMBER(4)
 FISCAL_YEAR_ID 			   NOT NULL NUMBER
 DAYS_IN_CAL_YEAR			   NOT NULL NUMBER
 DAYS_IN_FIS_YEAR			   NOT NULL NUMBER
 END_OF_CAL_YEAR			   NOT NULL DATE
 END_OF_FIS_YEAR			   NOT NULL DATE

如果我们创建一个物化视图

create materialized view sales_month_sum 
enable query rewrite as 
  SELECT t.calendar_month_id,
         prod_id,
         channel_id,
         promo_id,
         SUM (quantity_sold) quantity_sold,
         SUM (amount_sold) amount_sold
    FROM sales s, times t
   WHERE s.time_id = t.time_id
GROUP BY prod_id,
         channel_id,
         promo_id,
         t.calendar_month_id;

如果我们做如下按月的分组查询

SQL> alter session set query_rewrite_enabled=true;
SQL> alter session set query_rewrite_integrity=trusted;
SQL> set autotrace traceonly
SQL> set line 200
SQL>   SELECT t.calendar_month_id,
         prod_id,
         channel_id,
         promo_id,
         SUM (quantity_sold) quantity_sold,
         SUM (amount_sold) amount_sold
    FROM sales s, times t
   WHERE s.time_id = t.time_id
GROUP BY prod_id,
         channel_id,
         promo_id,
         t.calendar_month_id; 

9068 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 3287305789

------------------------------------------------------------------------------------------------
| Id  | Operation		     | Name	       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	     |		       |  9068 |   690K|    13	 (0)| 00:00:01 |
|   1 |  MAT_VIEW REWRITE ACCESS FULL| SALES_MONTH_SUM |  9068 |   690K|    13	 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------

可见查询使用的是物化视图,但是如果我需要按年、季度对数据做分组查询呢?

  SELECT t.calendar_quarter_id,prod_id,
         channel_id,
         promo_id,
         SUM (quantity_sold) quantity_sold,
         SUM (amount_sold) amount_sold
    FROM sales s, times t
   WHERE s.time_id = t.time_id
GROUP BY prod_id,
         channel_id,
         promo_id,
         t.calendar_quarter_id;

这个查看肯定是不能使用物化视图的,执行计划如下

Execution Plan
----------------------------------------------------------
Plan hash value: 3221963832

---------------------------------------------------------------------------------------------------------
| Id  | Operation		      | Name	| Rows	| Bytes | Cost (%CPU)| Time	| Pstart| Pstop |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	      | 	|  2037 | 79443 |   569   (6)| 00:00:07 |	|	|
|   1 |  HASH GROUP BY		      | 	|  2037 | 79443 |   569   (6)| 00:00:07 |	|	|
|*  2 |   HASH JOIN		      | 	|   918K|    34M|   546   (2)| 00:00:07 |	|	|
|   3 |    PART JOIN FILTER CREATE    | :BF0000 |  1826 | 21912 |    18   (0)| 00:00:01 |	|	|
|   4 |     TABLE ACCESS FULL	      | TIMES	|  1826 | 21912 |    18   (0)| 00:00:01 |	|	|
|   5 |    PARTITION RANGE JOIN-FILTER| 	|   918K|    23M|   525   (2)| 00:00:07 |:BF0000|:BF0000|
|   6 |     TABLE ACCESS FULL	      | SALES	|   918K|    23M|   525   (2)| 00:00:07 |:BF0000|:BF0000|
---------------------------------------------------------------------------------------------------------

Oracle为了是查询重写更加的智能,引入了Dimension的概念。Dimension我们称之为维,它是基于维度表的,用来描述维度表的维度之间的层级关系。

CREATE DIMENSION SH.TIMES_DIM
  LEVEL DAY                            IS 
    (SH.TIMES.TIME_ID)
  LEVEL MONTH                          IS 
    (SH.TIMES.CALENDAR_MONTH_ID)
  LEVEL QUARTER                        IS 
    (SH.TIMES.CALENDAR_QUARTER_ID)
  LEVEL YEAR                           IS 
    (SH.TIMES.CALENDAR_YEAR_ID)
  HIERARCHY CAL_ROLLUP
    (DAY                               CHILD OF
     MONTH                             CHILD OF
     QUARTER                           CHILD OF
     YEAR);

LEVEL定义等级,基于维度表,HIERARCHY关键字定义层级关系。由层级关系,我们知道quarter是由month组成的。

我们再次查询

SQL> SELECT t.calendar_quarter_id,prod_id,
         channel_id,
         promo_id,
         SUM (quantity_sold) quantity_sold,
         SUM (amount_sold) amount_sold
    FROM sales s, times t
   WHERE s.time_id = t.time_id
GROUP BY prod_id,
         channel_id, 
         promo_id,
         t.calendar_quarter_id;

3375 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 3397140165

--------------------------------------------------------------------------------------------------
| Id  | Operation		       | Name		 | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	       |		 |    20 |  1720 |    36  (14)| 00:00:01 |
|   1 |  HASH GROUP BY		       |		 |    20 |  1720 |    36  (14)| 00:00:01 |
|*  2 |   HASH JOIN		       |		 |   128K|    10M|    33   (7)| 00:00:01 |
|   3 |    VIEW 		       |		 |   849 |  6792 |    19   (6)| 00:00:01 |
|   4 |     HASH UNIQUE 	       |		 |   849 |  6792 |    19   (6)| 00:00:01 |
|   5 |      TABLE ACCESS FULL	       | TIMES		 |  1826 | 14608 |    18   (0)| 00:00:01 |
|   6 |    MAT_VIEW REWRITE ACCESS FULL| SALES_MONTH_SUM |  9068 |   690K|    13   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

这次是使用物化视图与times表做关联,性能更高了。

我们对比如下两个查询

SQL>   SELECT t.calendar_quarter_id,
         prod_id,
         channel_id,
         promo_id,
         SUM (quantity_sold) quantity_sold,
         SUM (amount_sold) amount_sold
    FROM sales s, times t
   WHERE s.time_id = t.time_id AND t.calendar_quarter_id = 1769
GROUP BY prod_id,
         channel_id,
         promo_id,
         t.calendar_quarter_id; 

168 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 3397140165

--------------------------------------------------------------------------------------------------
| Id  | Operation		       | Name		 | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	       |		 |     1 |    86 |    33   (7)| 00:00:01 |
|   1 |  HASH GROUP BY		       |		 |     1 |    86 |    33   (7)| 00:00:01 |
|*  2 |   HASH JOIN		       |		 |  6423 |   539K|    32   (4)| 00:00:01 |
|   3 |    VIEW 		       |		 |    34 |   272 |    19   (6)| 00:00:01 |
|   4 |     HASH UNIQUE 	       |		 |    34 |   272 |    19   (6)| 00:00:01 |
|*  5 |      TABLE ACCESS FULL	       | TIMES		 |    90 |   720 |    18   (0)| 00:00:01 |
|   6 |    MAT_VIEW REWRITE ACCESS FULL| SALES_MONTH_SUM |  9068 |   690K|    13   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

使用了物化视图

SQL>SELECT t.calendar_quarter_id,
         prod_id,
         channel_id,
         promo_id,
         SUM (quantity_sold) quantity_sold,
         SUM (amount_sold) amount_sold
    FROM sales s, times t
   WHERE s.time_id = t.time_id AND t.calendar_quarter_desc = ‘1998-01‘
GROUP BY prod_id,
         channel_id,
         promo_id,
         t.calendar_quarter_id;

168 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 3221963832

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation		      | Name	| Rows	| Bytes |TempSpc| Cost (%CPU)| Time	| Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	      | 	|  8146 |   373K|	|   848   (2)| 00:00:11 |	|	|
|   1 |  HASH GROUP BY		      | 	|  8146 |   373K|  3632K|   848   (2)| 00:00:11 |	|	|
|*  2 |   HASH JOIN		      | 	| 57459 |  2637K|	|   546   (2)| 00:00:07 |	|	|
|   3 |    PART JOIN FILTER CREATE    | :BF0000 |    91 |  1820 |	|    18   (0)| 00:00:01 |	|	|
|*  4 |     TABLE ACCESS FULL	      | TIMES	|    91 |  1820 |	|    18   (0)| 00:00:01 |	|	|
|   5 |    PARTITION RANGE JOIN-FILTER| 	|   918K|    23M|	|   525   (2)| 00:00:07 |:BF0000|:BF0000|
|   6 |     TABLE ACCESS FULL	      | SALES	|   918K|    23M|	|   525   (2)| 00:00:07 |:BF0000|:BF0000|
-----------------------------------------------------------------------------------------------------------------

没有使用物化视图。

其实条件实质上是一样的,因为t.calendar_quarter_desc = ‘1998-01‘ 和t.calendar_quarter_id = 1769 在times表中表示相同的数据。

但是Oracle不知道CALENDAR_QUARTER_DESC与CALENDAR_QUARTER_ID的关系。

我们在创建Dimension时,可以为LEVEL指定属性值。

如下

CREATE DIMENSION SH.TIMES_DIM
  LEVEL DAY                            IS 
    (SH.TIMES.TIME_ID)
  LEVEL MONTH                          IS 
    (SH.TIMES.CALENDAR_MONTH_ID)
  LEVEL QUARTER                        IS 
    (SH.TIMES.CALENDAR_QUARTER_ID)
  LEVEL YEAR                           IS 
    (SH.TIMES.CALENDAR_YEAR_ID)
  HIERARCHY CAL_ROLLUP
    (DAY                               CHILD OF
     MONTH                             CHILD OF
     QUARTER                           CHILD OF
     YEAR)
  ATTRIBUTE QUARTER DETERMINES 
    (SH.TIMES.CALENDAR_QUARTER_DESC,
     SH.TIMES.DAYS_IN_CAL_QUARTER,
     SH.TIMES.END_OF_CAL_QUARTER,
     SH.TIMES.CALENDAR_QUARTER_NUMBER)
  ATTRIBUTE YEAR DETERMINES 
    (SH.TIMES.CALENDAR_YEAR,
     SH.TIMES.DAYS_IN_CAL_YEAR,
     SH.TIMES.END_OF_CAL_YEAR);

我们再次查询

SQL> SELECT t.calendar_quarter_id,
         prod_id,
         channel_id,
         promo_id,
         SUM (quantity_sold) quantity_sold,
         SUM (amount_sold) amount_sold
    FROM sales s, times t
   WHERE s.time_id = t.time_id AND t.calendar_quarter_desc = ‘1998-01‘
GROUP BY prod_id,
         channel_id,
         promo_id,
         t.calendar_quarter_id;  

168 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 3290467316

--------------------------------------------------------------------------------------------------
| Id  | Operation		       | Name		 | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	       |		 |    20 |  2240 |    33   (7)| 00:00:01 |
|   1 |  HASH GROUP BY		       |		 |    20 |  2240 |    33   (7)| 00:00:01 |
|*  2 |   HASH JOIN		       |		 | 17191 |  1880K|    32   (4)| 00:00:01 |
|   3 |    VIEW 		       | VW_GBF_5	 |    91 |  3094 |    19   (6)| 00:00:01 |
|   4 |     HASH GROUP BY	       |		 |    91 |   728 |    19   (6)| 00:00:01 |
|   5 |      VIEW		       |		 |    91 |   728 |    19   (6)| 00:00:01 |
|   6 |       HASH UNIQUE	       |		 |    91 |  1456 |    19   (6)| 00:00:01 |
|*  7 |        TABLE ACCESS FULL       | TIMES		 |    91 |  1456 |    18   (0)| 00:00:01 |
|   8 |    MAT_VIEW REWRITE ACCESS FULL| SALES_MONTH_SUM |  9068 |   690K|    13   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

这次就使用了物化视图。

时间: 2024-09-30 04:21:49

Oracle 学习之 数据仓库(二) Dimension 的理解的相关文章

oracle学习笔记(二)

设置归档模式(mount状态) ALTER database ARCHIVELOG; //关闭数据库 shutdown immediate //启动数据库到mount状态 startup mount alter database archivelog; //查看归档状态 archive log list; SQL> archive log list; 数据库日志模式 存档模式 自动存档 启用 存档终点 USE_DB_RECOVERY_FILE_DEST 最早的联机日志序列 1 下一个存档日志序列

【我的Oracle学习笔记(二)】----- select语句补充

一.多表查询 多表查询是指从多个有关联的表中查询数据,其语法与单表查询类似.一般来说,多表查询的表要用连接联系起来,如果没连接,则查询结果是这多个查询表的笛卡尔积(注释1). 模拟查询雇员姓名和所在部门名称: select [雇员姓名],[部门名称] from [雇员表] a,scott,[部门表] b where a.[部门编号]=b.[部门编号]; 上例中,为每一个查询表指定了别名,便于SQL语句的书写. 模拟查询在”sales“部门工作的雇员其雇员姓名 select [雇员姓名] from

Oracle 学习之数据仓库(一)导入Oracle 11g Global samples schema

Oracle 11g 提供了数据仓库的示例schema,可以通过如下链接下载示例安装文件. http://www.oracle.com/technology/products/bi/olap/doc_sample_schemas/global_11g_schema.zip 将下载的文件上传至Oracle服务器,并解压. [[email protected] ~]$ mkdir global_11g_schema      [[email protected] ~]$ unzip -d globa

Oracle学习笔记(十二)

十三.存储过程和存储函数1.掌握存储过程(相当于建立一个函数或者方法体,然后通过外部对其调用) 指存储在数据库中供所有程序调用的子程序叫做存储过程或存储函数. 相同点: 完成特定功能的程序 区别: 是否用return语句返回值 (1)创建和使用存储过程 用create procedure命令建立存储过程和存储函数 语法: create or replace procedure 过程名(参数列表) as PL/SQL 子程序体(说明部分); 事例: (a)打印一个存储过程:打印HelloWorld

oracle学习篇十二:索引

索引: 查询User_indexes可以获取有关用户已创建的索引的详细信息. 查询User_ind_partitions可以获取有关用户已创建的分区索引的详细信息. 查询User_ind_columns可以获取有关列(用户的索引是基于这些列创建的)的详细信息. 索引类型:唯一索引.组合索引.反向键索引.位图索引和基于函数的索引. 索引在逻辑上物理上都独立于关联表中的数据,在任何时候都可以创建或删除索引,而不会影响基表或其它索引. 1.创建普通索引的语法:Create INDEX index_na

Oracle学习笔记(二)——临时表

在针对大数据量的多表级联查询或复杂事务处理的时候,引入Oracle临时表是一种不错的策略.因此,在解决实际需求时经常会遇到需要使用存储过程和临时表相互配合的情况.下面就Oracle如何创建临时表以及注意事项做出总结: 一.创建临时表 Oracle临时表分为回话期和事务期两种类型,他们的创建语法基本一致: 会话期临时表 CREATE GLOBAL TEMPORARY TABLE ON COMMIT PRESERVE ROWS; 事务期临时表 CREATE GLOBAL TEMPORARY TABL

oracle学习篇:二、参数文件

2 参数文件 2.1 参数文件的获取 oracle的初始化参数可以通过查询v$parameter视图得到,在SQL*PLUS中,可以用过show parameter命令来显示某些参数的设置值. 2.2 参数文件 初始化参数文件:pfile 服务器参数文件:spfile 视图v$spparamter记录spfile参数的设置. 没啥好说的,直接学习一下案例分析. 2.3 诊断案例 问题描述:数据库在重新启动时无法正常启动,检查发现undo表空间丢失. 2.3.1 检查alert日志文件 警报日志文

Oracle学习笔记(二)----------union

趁热再整理一个关于数据库(Oracle)的关键字的用法 union关键字 union字面意思就是“联合”,通过该关键字可以将两个sql语句合并起来一起查询,以达到想要的查询结果. 举个例子 设有表如下: 学生表: +----+------+------+---------+ | id | name | age | classid | +----+------+------+---------+ | 1 | 关羽 | 35 | 7班 | | 2 | 张飞 | 33 | 5班 | | 3 | 赵云

Oracle 学习之RAC(二) 环境准备

本次安装选择VMmare Workstation 10.0.1 ,创建四台虚拟机.如下: Openfiler (openfileresa-2.99.1-x86_64) 机器名 IP地址 openfiler.localdomain.com 192.168.199.219 RAC节点  (OracleLinux-R6-U4-Server-x86_64) 机器名 Public-IP Private-IP VIP 11grac1 192.168.199.10 192.168.10.10 192.168.