使用Aggregate子查询作为父查询的参数的替代方法

时间:2018-02-13 21:37:26

标签: sql oracle

我有一个非常大的非分区表,需要很长时间才能返回此查询的结果:

ProjectB

当我单独使用这个子查询时,需要12分钟才能运行:

SELECT 
    (SELECT Listagg(VALUE_STRING, ', ') 
            WITHIN GROUP (ORDER BY VALUE_STRING) AS VALUE_STRING 
     FROM   ATTRIBUTE_DATA AD 
     WHERE  AD.id = DT.dataid 
            AND AD.defid = 3070056 
            AND AD.attrid = 4 
            AND vernum = (SELECT Max(vernum) 
                        FROM   ATTRIBUTE_DATA AD
                        WHERE  AD.id = DT.dataid 
                                AND AD.defid = 3070056 
                                AND AD.attrid = 4) 
            AND defvern = (SELECT Max(defvern) 
                        FROM   ATTRIBUTE_DATA AD
                        WHERE  AD.id = DT.dataid 
                                AND AD.defid = 3070056 
                                AND AD.attrid = 4) 
    GROUP  BY AD.id) AS PlantNumbers
FROM WORKTABLE W 
    left outer join CUSTOM_FORMS FORMS 
                ON FORMS.volumeid = w.subwork_subworkid 
                    AND FORMS.versionnum = -1 
                    AND FORMS.rowseqnum = 1 
    left outer join DATATREE DT
                ON DT.name = FORMS.document_number_text_field 
                    AND DT.ownerid = -2000 
                    AND DT.SUBTYPE = 144 
                    AND DT.dataid NOT IN (SELECT dataid 
                                        FROM   dtreeancestors 
                                        WHERE  ancestorid = 3109628) 

如何改进此脚本。

2 个答案:

答案 0 :(得分:1)

我甚至不确定你的问题是什么,但对于这个问题:

SELECT Max(vernum) 
FROM   ATTRIBUTE_DATA AD
WHERE  AD.id = DT.dataid 
   AND AD.defid = 3070056 
   AND AD.attrid = 4

您需要ATTRIBUTE_DATA(dataid, defid, attrid, vernum)上的索引。

这可能会加快速度。

答案 1 :(得分:0)

从头开始,WORKTABLE有多大似乎正在推动查询?如果它是一千万行,那么你将进行一千万次聚合。这是很多工作而且会很痛苦。

WORKTABLE加入CUSTOM_FORMS,然后加入DATATREE。由于您是通过DATATREE.data_id提取数据,因此您只对链接到DATATREE的WORKTABLE条目感兴趣,因此您可以使用常规内连接,而不是外连接。

对于每个DATATREE数据ID,您在标量子查询中进行聚合。 GROUP BY AD.id是多余的,如果查询返回多行,标量子查询将返回错误。

我们不知道您将为每个WORKTABLE条目聚合ATTRIBUTE_DATA中的行数。它必须少于几百,否则你可能会为LISTAGG吹掉4000个字符的限制。

Oracle主要是一个关系数据库。看起来您的应用程序正在尝试在那里实现一些通用/模式类模型,其中所有内容都可以自定义,而不是将属性存储为表中的列。如果你真的需要走这条路,那么Oracle / RDBMS并不是构建它的好平台。如果为时已晚,请查看分区,物化视图和基于函数的索引,并尝试在通用索引之上对关系模型进行分层。