我有一个非常大的非分区表,需要很长时间才能返回此查询的结果:
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)
如何改进此脚本。
答案 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并不是构建它的好平台。如果为时已晚,请查看分区,物化视图和基于函数的索引,并尝试在通用索引之上对关系模型进行分层。