Stuck in a rut. I’m on constraints this week. It all started with “something about nothing” – complete misunderstandings about NULL values, especially in indexes. Now I’m stuck on constraints. Just today I was giving a seminar session – and one of the topics was “Effective Schema” – all about constraints, using the right types, telling the CBO more information. This is an example I’ve used in that section.

I’ve been asked in the past “Why should I use a primary key? Why not just use a unique index?” Well, the answer is that you could, but doesn’t the fact you used a primary key say something over and above just using a unique index? In fact it does – it can say a lot. The same goes for the use of foreign keys, NOT NULL constraints and others – they not only protect the data, they add information about the data into the data dictionary. Using this additional information Oracle is able to perform a query rewrite more often, in many complex cases.

Consider the following small example. We will copy the EMP and DEPT tables from the SCOTT schema and create a materialized view that pre-joins the tables together for us.

ops$tkyte@ORA10GR2> create table emp
2  as
3  select * from scott.emp;
Table created.ops$tkyte@ORA10GR2> create table dept
2  as
3  select * from scott.dept;
Table created.ops$tkyte@ORA10GR2> create materialized view emp_dept
2  build immediate
3  refresh on demand
4  enable query rewrite
5  as
6  select dept.deptno, dept.dname, count (*)
7    from emp, dept
8   where emp.deptno = dept.deptno
9   group by dept.deptno, dept.dname
10  /
Materialized view created.

Now, we have withheld a lot of information from Oracle here. It does not understand the relationship between EMP and DEPT, does not know what columns are primary keys, and so on. Now, let’s run a query and see what happens:

ops$tkyte@ORA10GR2> set autotrace on
ops$tkyte@ORA10GR2> select count(*) from emp;COUNT(*)
----------14Execution Plan
-------------------------------------------...
Plan hash value: 2083865914---------------------------------------------...
| Id  | Operation          | Name | Rows  | C...
---------------------------------------------...
|   0 | SELECT STATEMENT   |      |     1 |  ...
|   1 |  SORT AGGREGATE    |      |     1 |  ...
|   2 |   TABLE ACCESS FULL| EMP  |    14 |  ...
---------------------------------------------...

Now, you and I know that the count(*) could easily, and more efficiently (especially if the number of employees in each department was large and there were lots of departments), have been answered from the materialized view. There we have all of the information we need to get the count of employees. We know that because we know things about the data that we kept from Oracle:

  • DEPTNO is the primary key of DEPT. That means that each EMP record will join to at most one DEPT record.
  • DEPTNO in EMP is a foreign key to DEPTNO in DEPT. If the DEPTNO in EMP is not a null value, then it will be joined to a row in DEPT (we won’t lose any non-null EMP records during a join)
  • DEPTNO in EMP is NOT NULL – this coupled with the foreign key constraint tells us we won’t lose any EMP records.

These three facts imply that if we join EMP to DEPT – each EMP row will be observed in the result set AT LEAST once and AT MOST once. Since we never told Oracle these facts, it was not able to make use of the materialized view. So, let’s make Oracle aware of them:

ops$tkyte@ORA10GR2> alter table dept
2  add constraint
3  dept_pk
4  primary key(deptno);
Table altered.ops$tkyte@ORA10GR2> alter table emp
2  add constraint
3  emp_fk_dept
4  foreign key(deptno)
5  references dept(deptno);
Table altered.ops$tkyte@ORA10GR2> alter table emp
2  modify deptno not null;
Table altered.ops$tkyte@ORA10GR2> set autotrace on
ops$tkyte@ORA10GR2> select count(*) from emp;COUNT(*)
----------14Execution Plan
---------------------------------------------------...
Plan hash value: 155013515---------------------------------------------------...
| Id  | Operation                     | Name     | ...
---------------------------------------------------...
|   0 | SELECT STATEMENT              |          | ...
|   1 |  SORT AGGREGATE               |          | ...
|   2 |   MAT_VIEW REWRITE ACCESS FULL| EMP_DEPT | ...
---------------------------------------------------...

And now Oracle is able to rewrite the query using the materialized view. Anytime that you know Oracle could use a materialized view, but it is not doing so (and you have verified you can use materialized views in general) – take a closer look at the data and ask yourself “what piece of information have I withheld from Oracle?” Nine times out of ten, you'll find a missing piece of metadata that, when included, allows Oracle to rewrite the query.

So, what happens if this is a true data warehouse and there are tens of millions of records in the above tables? You don’t really want the additional effort of verifying a foreign key relationship – you already did that in your data scrubbing routine didn’t you? In which case, you can create a non-validated constraint – one that is used to inform the database about a relationship but that has not been validated by the database itself. Let’s look at the above example again but this time we’ll simulate a load of data into an existing data warehouse (our example above is our data warehouse). We’ll drop our constraints, load the data, refresh the materialized views and add our constraints back. We’ll start with dropping the constraints:

ops$tkyte@ORA10GR2> alter table emp drop constraint emp_fk_dept;
Table altered.ops$tkyte@ORA10GR2> alter table dept drop constraint dept_pk;
Table altered.ops$tkyte@ORA10GR2> alter table emp modify deptno null;
Table altered.

Now, in order to simulate our load, I will insert a single new row into EMP (not much of a load but enough to demonstrate with). Then, we will refresh our materialized view:

ops$tkyte@ORA10GR2> insert into emp (empno,deptno) values ( 1, 1 );
1 row created.ops$tkyte@ORA10GR2> exec dbms_mview.refresh( 'EMP_DEPT' );
PL/SQL procedure successfully completed.

purposely inserted a row into EMP that will violate the constraint we are about to put back on the EMP. This is to show you what can happen if you tell Oracle to trust your data and the data is invalid. It shows that Oracle will trust you but - Oracle will give you the wrong answer – though through no fault of its own. When you use these constraints on a large warehouse, you had better be very sure of the data. Now we tell Oracle about the relationships between EMP and DEPT:

ops$tkyte@ORA10GR2> alter table dept
2  add constraint dept_pk primary key(deptno)
3  RELY enable NOVALIDATE
4  /
Table altered.ops$tkyte@ORA10GR2> alter table emp
2  add constraint emp_fk_dept
3  foreign key(deptno) references dept(deptno)
4  RELY enable NOVALIDATE
5  /
Table altered.ops$tkyte@ORA10GR2> alter table emp modify deptno not null NOVALIDATE;
Table altered.

So here we have told Oracle that there is a foreign key from EMP to DEPT as before, but this time we have told Oracle to trust that if it joins EMP to DEPT by DEPTNO – every row in EMP will be retrieved at least once and at most once. Oracle will perform no validating checks. That is the purpose of the NOVALIDATE and RELY options. The NOVALIDATE bypasses the checking of existing data we loaded, RELY tells Oracle to “rely” on the integrity of the data. We are now ready to query:

ops$tkyte@ORA10GR2> alter session set query_rewrite_integrity=enforced;
Session altered.ops$tkyte@ORA10GR2> select count(*) from emp;COUNT(*)
----------15Execution Plan
----------------------------------------------...
Plan hash value: 2083865914----------------------------------------------...
| Id  | Operation          | Name | Rows  | Co...
----------------------------------------------...
|   0 | SELECT STATEMENT   |      |     1 |   ...
|   1 |  SORT AGGREGATE    |      |     1 |   ...
|   2 |   TABLE ACCESS FULL| EMP  |    15 |   ...
----------------------------------------------...

This time QUERY_REWRITE_INTEGRITY=ENFORCED is not good enough to cause a rewrite of our query as you can see. Oracle did not rewrite the query to use the materialized view because of this. We must go down a level in query integrity. We need Oracle to “trust” us:

ops$tkyte@ORA10GR2> alter session set query_rewrite_integrity=trusted;
Session altered.ops$tkyte@ORA10GR2> select count(*) from emp;COUNT(*)
----------14Execution Plan
--------------------------------------------------...
Plan hash value: 155013515------------------------------------------------------...
| Id  | Operation                     | Name     | Row...
------------------------------------------------------...
|   0 | SELECT STATEMENT              |          |    ...
|   1 |  SORT AGGREGATE               |          |    ...
|   2 |   MAT_VIEW REWRITE ACCESS FULL| EMP_DEPT |    ...
------------------------------------------------------...

So, here Oracle did in fact rewrite the query but as you can see – the side effect of that in this case is the wrong answer is returned. The reason we got the wrong answer is because the “fact” that each row in EMP would be preserved in a join to DEPT is not a fact given the data we loaded. When the materialized view refreshed, it did not get the newly added EMP row. The data we told Oracle to rely on was not reliable. This demonstration points out two things:

  • You can use materialized views in a large data warehouse very efficiently, without having to perform lots of extra, typically redundant, verifications of the data.
  • BUT, you had better be 100% sure that your data is scrubbed if you ask Oracle to rely on it.

POSTED BY THOMAS KYTE AT 4:42 PM 

POST A COMMENT


22 COMMENTS:

 Howard J. Rogers said....

Nice demo. I intend to steal it shamelessly whenever I next get blank stares when I start mentioning the RELY flag!

MON JAN 30, 06:41:00 PM EST  

rely constraint相关推荐

  1. RELY constraints

    数据仓库中的数据,一般是通过ETL定期load进来的.在做ETL的时候,一般会对load的数据的一致性做检查.所以,我们有理由认为,数据仓库中的数据都是符合一致性要求的.那么,在数据仓库中的表上还有必 ...

  2. oracle 11g 逻辑备库,通过Oracle 11g 逻辑standby实现BI的需求

    逻辑standby用的很少,特别是在11g,物理standby也可以只读打开并实时应用,物理standby也可以做滚动升级.不过,最近有一个用户需求,要建一个报表系统数据库,想到可以试试逻辑stand ...

  3. [索引]引用Balancing bike sharing systems with constraint programming的文章

    文章目录 1. Dynamic container drayage with uncertain request arrival times and service time windows 2. P ...

  4. Oracle里面constraint说明

    首先来看一下<SQL Reference>中对于Constraint的说明:             下面说一下我的认识:       1.Constraints的目的:         ...

  5. 默认约束 oracle,ORACLE约束(constraint):对象的强制规定

    ORACLE约束(constraint):对象的强制规定 5种约束: NOT NULL     非空 NN UNIQUE       唯一 UK PRIMARY KEY  主键 PK FOREIGN ...

  6. oracle 提示:ORA-02292:integrity constraint(xxxxxxx) violated - child record found

    当我们删除 数据的时候 oracle 提示:ORA-02292:integrity constraint(xxxxxxx) violated - child record found 这种情况呢是因为 ...

  7. Postgresql:INSERT INTO ON CONSTRAINT pk_key_id do nothing

    一.Postgresql在插入数据有主键或者唯一键冲突时,可以不做任何操作,也可以update 1. do nothing INSERT INTO t_test(id,name) VALUES (10 ...

  8. It is not safe to rely on the system's timezone settings

    在写php程序中有时会出现这样的警告: PHP Warning: date(): It is not safe to rely on the system's timezone settings. Y ...

  9. 阅读Book:MultiObjective using Evolutionary Algorithms(7)---Weighted Sum Methods ε-Constraint Methods

    (1) Classical multi-objective optimization methods have been around for at least four decades. (2)   ...

最新文章

  1. 消息队列系列(三):.Rabbitmq Trace的使用
  2. node.js 调试 eggs launch.json配置信息
  3. 原理图、PCB和实物是如何对应起来的
  4. P4173-残缺的字符串【FFT】
  5. python之工作举例:通过复制NC文件来造数据
  6. 外设驱动库开发笔记2:AD8400系列数字电位器驱动
  7. Activity的四种启动模式和onNewIntent()
  8. linux系统备份和恢复
  9. 2021年中国少儿编程行业报告
  10. 用Android Sutdio调试NDK
  11. 情人节民宿预定量同比增200% 北京建国门最火
  12. 技术选择真的没有那么重要
  13. android webview 例子,android – webview shouldinterceptrequest示例
  14. 启动、停止、重启 MySQL 常见的操作方法:
  15. Linux 内核通知链(notifier chain)原理和使用方法
  16. 龙芯3A4000处理器简介
  17. Android NE问题分析方法介绍
  18. php太平洋时间转成北京时间,北京时间 → 太平洋时间 换算表 和太平洋时间 → 北京时间 换算表...
  19. 理解VML||MKL
  20. 设置共享文件夹在主机与本地VMware虚拟机之间传输文件

热门文章

  1. mac电脑真正好用且实用的软件(不断积累)
  2. 爬取天涯论坛数据,看看大家都在讨论什么
  3. 【数据可视化】第三章——数据可视化综合实践
  4. 人工智能未来会取代人类吗?AI智能,科技正在改变我们的历史
  5. robots机器人疾风 war_warrobots
  6. 震惊,使用imba.io框架,得到比 vue 快50倍的性能基准
  7. MobaXterm批量导入sessions
  8. CentOS 7 NIS 配置
  9. 显示屏在线测试软件,Monitor Test Screens显示器测试
  10. UserWarning: semaphore_tracker: There appear to be 4 leaked semaphores to clean up at shutdown