我已将表结构(没有主键和外键约束),数据,索引(所有索引)从一个模式复制到另一个模式。
尝试运行具有多个联接的选择查询(在新架构中)时,比在旧架构中运行相同查询(带有约束)需要更长的时间。
省略的外键和主键约束是否是导致性能滞后的原因?
答案 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")