select query performance Vs primary,foreign key

时间:2016-08-02 10:46:40

标签: oracle referential-integrity

我已将表结构(没有主键和外键约束),数据,索引(所有索引)从一个模式复制到另一个模式。

尝试运行具有多个联接的选择查询(在新架构中)时,比在旧架构中运行相同查询(带有约束)需要更长的时间。

省略的外键和主键约束是否是导致性能滞后的原因?

2 个答案:

答案 0 :(得分:0)

在将对象从一个环境导入到另一个环境时,我遇到了类似的性能问题,然后我添加了缺少的约束,然后我看到了性能方面的良好改进。 因此,我会请求您添加约束,然后运行您的连接查询。

答案 1 :(得分:0)

首先,主键和唯一键也是索引(也就是说,索引支持约束),因此缺少主键或唯一键可能意味着缺少索引。

此外,如果存在约束,优化器可以应用一些转换。例如,考虑以下查询(使用Oracle HR演示模式):

select count(*)
from   employees e
       join departments d on d.department_id = e.department_id;

执行计划:

--------------------------------------------------------------------------------------
| Id  | Operation        | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                   |     1 |     3 |     0   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE  |                   |     1 |     3 |            |          |
|*  2 |   INDEX FULL SCAN| EMP_DEPARTMENT_IX |   106 |   318 |     0   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("E"."DEPARTMENT_ID" IS NOT NULL)

请注意,没有引用departments。优化器知道department_id中的employees必须存在于departments中,因为有一个强制执行此操作的外键,并且它只能在departments中出现一次,因为它是主要的键。因此,不需要实际评估连接,因为它要做的就是检查e.department_id是否不为空。由于该列上有一个索引,它可以将索引视为一个瘦表,甚至不触摸employees。 (如果将e.department_id定义为not null,则甚至不需要该过滤器。)

现在看看如果禁用约束会发生什么:

SQL> alter table employees disable constraint EMP_DEPT_FK;

Table altered.

SQL> select count(*)
  2  from   employees e
  3         join departments d on d.department_id = e.department_id;

  COUNT(*)
----------
       106

SQL> @xplan
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
Compatibility is set to 12.2.0.0.0

Plan hash value: 1475840611

-----------------------------------------------------------------------------------------
| Id  | Operation           | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |                   |     1 |     7 |     0   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE     |                   |     1 |     7 |            |          |
|   2 |   NESTED LOOPS      |                   |   106 |   742 |     0   (0)| 00:00:01 |
|   3 |    INDEX FULL SCAN  | EMP_DEPARTMENT_IX |   107 |   321 |     0   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN| DEPT_ID_PK        |     1 |     4 |     0   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("D"."DEPARTMENT_ID"="E"."DEPARTMENT_ID")