加入 2 个脚本 ORACLE 时的 SQL 性能

Posted

技术标签:

【中文标题】加入 2 个脚本 ORACLE 时的 SQL 性能【英文标题】:SQL Performance on joining 2 scripts ORACLE 【发布时间】:2017-09-06 08:20:16 【问题描述】:

我有两个脚本,很复杂,一个是我自己写的,另一个是 10 年前写的。第一个脚本获取必要的 id 并在大约 30 秒内执行,例如:

| ID | some other info ...
+----+--------------------
| 1  |       ...
| 2  |       ...
| 3  |       ...
| 4  |       ...

第二个脚本获取的是一些比较复杂的数据,是通过很多子查询计算出来的,执行时间大概在30秒左右,例如:

| ID | Computed Info
+----+--------------------
| 1  |       111
| 2  |       222
| 3  |       333
| 4  |       444

现在我的 script1 需要包含来自 script2 的部分结果,因为 script2 非常复杂,很难分解必要的部分,这就是为什么我尝试使用 ID 将 script2 的连接结果留给 script1

SELECT TABLE1.*, TABLE2.COMPUTED_INFO FROM SCRIPT1 TABLE1 LEFT JOIN SCRIPT2 TABLE2 ON TABLE2.ID = TABLE1.ID

我得到的结果也是预期的结果是:

| ID | some other info ... | Computed Info
+----+---------------------+---------------
| 1  |       ...           |  111
| 2  |       ...           |  222
| 3  |       ...           |  333
| 4  |       ...           |  444

问题是在加入他们两个之后,执行时间现在是 20+ 分钟。

我也试过了

with table1 as 
             (script1), 
     table2 as 
             (script2) 
select t1.*, t2.computed_data 
from table1 t1 left join table2 t2 on t2.id = t1.id

这导致了 10+ 分钟。 我想知道为什么会发生这样的事情,当绝对 script1 和 script2 分别在大约 30 秒内分别运行时,但是当一起运行时,运行时间高达 10+ 还有其他方法可以实现吗?

【问题讨论】:

您是否尝试过在查询中运行EXPLAIN PLAN?输出是什么? @markusk 我没有,应该知道 @markusk 对于​​有问题的脚本2 我没有得到任何结果,并得到错误,指出超出了空间配额,对于它执行的脚本1,我应该从 plan_table 中注意哪一列?跨度> 有趣的部分不是script1script2 的单独执行计划,而是连接的执行计划。我怀疑您的问题是由script1script2 返回的大量行以及没有索引引起的。如果您可以display the explain plan 并将输出复制到您的问题中,那将有助于分析您的问题。 【参考方案1】:

您可以在加入这些表之前创建临时表。

首先创建表temp1 as select * from script1

并创建表 temp2 作为 select * from script2

然后选择您的查询

SELECT temp1.*, temp2.COMPUTED_INFO FROM temp1 TABLE1 LEFT JOIN temp2 TABLE2 ON temp2.ID = temp1.ID

【讨论】:

我对临时表进行了一些研究,似乎我需要定义它们一次,并且在需要时它们会被每个会话填充。我想知道是否可以避免使用临时表,并在 sql 查询中执行所有操作,或者至少是什么原因导致时间增加,因为 script1 在 x 时间实现,而 script2 在 y 时间实现,为什么我不能在 x+y 时间获得性能? 你能看到解释计划吗?如果你加入这些脚本,它有不同的解释计划。也许您可以尝试使用带有物质化提示的语句 我尝试为脚本创建临时表,但是将数据插入临时表需要 20 分钟,而简单地执行脚本大约需要 30 秒,我错过了什么吗? 你在运行选择查询时丢失了它并没有带来所有数据,例如在 toad 中它带来 500 行,所以它可能很快但所有数据都不是 一开始我也有类似的想法,但是script2返回的只有600+行,而script1返回45【参考方案2】:

上次遇到此类问题时,我使用临时表解决了它。我用 SCRIPT1 和 SCRIPT2 结果创建了临时表。然后将索引添加到 ID 列。

在此之后,与您的查询类似的查询必须执行得更快。

这发生在 postgresql 服务器上,但问题的根源是相同的。通常,RDBMS 无法优化来自 PROCEDURE/FUNCTION 的子查询/结果集,也无法在其行上使用索引。

【讨论】:

以上是关于加入 2 个脚本 ORACLE 时的 SQL 性能的主要内容,如果未能解决你的问题,请参考以下文章

在同一 SQL.Server 上跨 2 个数据库加入时的 COLLATE 问题

Toad for Oracle 10.6 与 11.5:编辑大型包时的性能问题

Oracle性能图表工具:awrcrt.sql

Oracle 性能慢排查脚本

使用python对oracle进行简单性能测试

使用Hibernate HQL从Oracle DB检索记录时的性能问题