select 查询性能与主键、外键
select query performance Vs primary,foreign key
我已经将 table 结构(没有主键和外键约束)、数据、索引(所有索引)从一个模式复制到另一个模式。
在尝试 运行 具有多个连接的 select 查询(在新模式中)时,它比 运行 在旧模式中执行相同查询花费的时间长得多(有限制)。
遗漏的外键和主键约束是否是这种性能滞后的原因?
我在将对象从一个环境导入到另一个环境时遇到了类似的性能问题,然后我添加了缺少的约束,然后我可以看到性能有了很好的改进。
因此,我会请您添加约束,然后 运行 您的连接查询。
首先,主键和唯一键也是索引(即约束由索引支持),因此缺少主键或唯一键可能意味着缺少索引。
此外,如果有约束,优化器可以应用一些转换。例如,考虑这个查询(使用 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
的引用。优化器知道 employees
中的 department_id
必须存在于 departments
中,因为有一个外键强制执行此操作,而且它只能在 departments
中出现一次,因为它是主要的钥匙。因此,不需要实际评估连接,因为它需要做的就是检查 e.department_id
是否不为空。由于该列上有一个索引,它可以将索引视为瘦 table,甚至不会触及 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")
我已经将 table 结构(没有主键和外键约束)、数据、索引(所有索引)从一个模式复制到另一个模式。
在尝试 运行 具有多个连接的 select 查询(在新模式中)时,它比 运行 在旧模式中执行相同查询花费的时间长得多(有限制)。
遗漏的外键和主键约束是否是这种性能滞后的原因?
我在将对象从一个环境导入到另一个环境时遇到了类似的性能问题,然后我添加了缺少的约束,然后我可以看到性能有了很好的改进。 因此,我会请您添加约束,然后 运行 您的连接查询。
首先,主键和唯一键也是索引(即约束由索引支持),因此缺少主键或唯一键可能意味着缺少索引。
此外,如果有约束,优化器可以应用一些转换。例如,考虑这个查询(使用 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
的引用。优化器知道 employees
中的 department_id
必须存在于 departments
中,因为有一个外键强制执行此操作,而且它只能在 departments
中出现一次,因为它是主要的钥匙。因此,不需要实际评估连接,因为它需要做的就是检查 e.department_id
是否不为空。由于该列上有一个索引,它可以将索引视为瘦 table,甚至不会触及 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")