sql - 为什么当我使用临时表时,oracle 中的查询需要更长的时间?

标签 sql database oracle oracle10g database-administration

ORACLE DB 中使用内部查询时,我遇到了一个特殊问题。我正在从具有大量记录的表中获取数据。 我正在使用的查询包含一个内部查询。

  • 当我直接在内部查询中提供值时,它会很多 更快。
  • 但是当我使用另一个(临时)表中完全相同的值时 无论是内部查询还是 JOIN,都需要更长的时间。

下面是查询:

更快的性能

SELECT   assembly_item_id menuItemId,
         location_id restId,
         bill_sequence_id,
         bill_config_id
  FROM   zil_ibat_resolve_bmi_ai_max_v
 WHERE   assembly_item_id = 8321
         AND location_id IN (82, 85, 116, .........)    

在内部部分使用选择查询时性能较低

没有 JOIN

SELECT   assembly_item_id menuItemId,
         location_id restId,
         bill_sequence_id,
         bill_config_id
  FROM   zil_ibat_resolve_bmi_ai_max_v
 WHERE   assembly_item_id = 8321
         AND location_id IN (SELECT   temp_id FROM global_temp_ids)

通过加入

SELECT   assembly_item_id menuItemId, location_id restId, bill_sequence_id, bill_config_id 
FROM   zil_ibat_resolve_bmi_ai_max_v t1
join global_temp_ids t2
on t1.location_id = t2.temp_id
WHERE   t1.assembly_item_id = 8321

注意:zil_ibat_resolve_bmi_ai_max_v 是一个 View 。

这个查询有什么问题?为什么我查询表而不是直接将 ID 放入内部部分会花费这么多时间?有替代方案吗?

解释计划

usedSelectQueryInInnerSection.png enter image description here

使用加入 enter image description here

在内部查询中输入数字 enter image description here

最佳答案

由于 View 结果和临时表之间存在 NESTED LOOP 连接,第二个和第三个查询速度很慢。将其更改为 HASH 连接,也许可以通过更好的优化器统计信息或 USE_HASH提示,应该加快查询速度。

问题

这部分位于执行计划的顶部:

NESTED LOOPS
    zil_ibat_resolve_bmi_ai_max_v
    global_temp_ids

类似于此伪代码:

for each row of zil_ibat_resolve_bmi_ai_max_v
    search index of global_temp_ids

根据图像, View 的执行计划在查询之间不会改变,该部分必须相对较快。并且临时表的查找使用唯一索引搜索,这也必须很快。但它的速度只是一次。我们可以从 Cardinality 1 看出Oracle 优化器认为它只会执行一次连接的内部部分。

嵌套循环在连接少量行时非常有用。当连接大量行时,哈希连接效果更好。

解决方案

更改连接方法的方法有很多,以下是首先尝试的两种:

1。收集统计信息。更好的优化器统计信息将改进基数估计,这通常会改进执行计划。收集统计数据的方法有很多,但通常默认设置是最好的。在这种情况下,可以通过运行如下过程来收集它们:exec dbms_stats.gather_schema_stats('SMART');对架构 ZILADMIN 和 XCBAIRAG 重复此操作。如果统计信息丢失或过时,调查默认统计信息收集作业未运行的原因也是一个好主意。

2。提示。 在生产代码中通常应避免提示,但它们至少仍然有助于诊断问题。使用提示 SELECT /*+ USE_HASH(t1 t2) */ ... 运行查询看看这是否会改善情况。如果有效,您可以保留提示或考虑使用其他形式的计划管理。例如,SQL Profile 可以以更简洁的方式解决这个问题和其他问题。请咨询其他开发人员或 DBA,了解您的系统中常见哪些类型的计划管理功能。

关于sql - 为什么当我使用临时表时,oracle 中的查询需要更长的时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23271546/

相关文章:

regex - Oracle 正则表达式尾随空格

sql - 在 Oracle SQL 中舍入为 0.5 或 1.0

sql - Spatialite SQL 查询以查找给定纬度/经度的最近节点

sql - 在 SQL Server 中如何将多行合并为一列?

php - 如何使用 PHP 从 xsd 文件动态检索基于父节点的节点号

SQL 连接两个表的列

java - 要计算 Oracle DB 中股票数据价格列表的移动平均值 - 使用 SQL 还是 Java 更快?

sql - 使用动态sql创建表

python - 如何并行对 pandas 数据帧执行多个 SQL 查询

python - 将python中的值保存到mysql数据库