Sql 在同一个表上具有多个联接的Oracle复杂查询
我正在处理oracle 11上的一个怪物查询(约800行),它占用了昂贵的资源 这里的主要问题是一个表Sql 在同一个表上具有多个联接的Oracle复杂查询,sql,oracle,query-optimization,sql-tuning,Sql,Oracle,Query Optimization,Sql Tuning,我正在处理oracle 11上的一个怪物查询(约800行),它占用了昂贵的资源 这里的主要问题是一个表movement,大约有1800万行,在这个表上我有30个左连接 LEFT JOIN mouvement mracct_ad1 ON mracct_ad1.code_portefeuille = t.code_portefeuille AND mracct_ad1.statut_ligne = 'PROPRE' AND substr(mracct_ad1.code_va
movement
,大约有1800万行,在这个表上我有30个左连接
LEFT JOIN mouvement mracct_ad1
ON mracct_ad1.code_portefeuille = t.code_portefeuille
AND mracct_ad1.statut_ligne = 'PROPRE'
AND substr(mracct_ad1.code_valeur,1,4) = 'MRAC'
AND mracct_ad1.code_transaction = t.code_transaction
LEFT JOIN mouvement mracct_zias
ON mracct_zias.code_portefeuille = t.code_portefeuille
AND mracct_zias.statut_ligne = 'PROPRE'
AND substr(mracct_zias.code_valeur,1,4) = 'PRAC'
AND mracct_zias.code_transaction = t.code_transaction
LEFT JOIN mouvement mracct_zixs
ON mracct_zias.code_portefeuille = t.code_portefeuille
AND mracct_zias.statut_ligne = 'XROPRE'
AND substr(mracct_zias.code_valeur,1,4) = 'MRAT'
AND mracct_zias.code_transaction = t.code_transaction
是否有某种方法可以消除左连接(联合连接或示例)以使查询更快、消耗更少?执行计划什么的?我想是吧。您的代码示例没有多大意义,但您可能可以执行条件聚合:
left join
(select m.code_portefeuille, m.code_transaction,
max(case when m.statut_ligne = 'PROPRE' and m.code_valeur like 'MRAC%' then ? end) as ad1,
max(case when m.statut_ligne = 'PROPRE' and m.code_valeur like 'MRAC%' then ? end) as zia,
. . . -- for all the rest of the joins as well
from mouvement m
group by m.code_portefeuille, m.code_transaction
) m
on m.code_portefeuille = t.code_portefeuille and m.code_transaction = t.code_transaction
您可能可以将所有30个联接替换为聚合表的单个联接。我猜是这样。您的代码示例没有多大意义,但您可能可以执行条件聚合:
left join
(select m.code_portefeuille, m.code_transaction,
max(case when m.statut_ligne = 'PROPRE' and m.code_valeur like 'MRAC%' then ? end) as ad1,
max(case when m.statut_ligne = 'PROPRE' and m.code_valeur like 'MRAC%' then ? end) as zia,
. . . -- for all the rest of the joins as well
from mouvement m
group by m.code_portefeuille, m.code_transaction
) m
on m.code_portefeuille = t.code_portefeuille and m.code_transaction = t.code_transaction
您可能可以将所有30个联接替换为聚合表的单个联接。请注意性能。通常,您希望“重新表述”条件,如:
AND substr(mracct_ad1.code_valeur,1,4) = 'MRAC'
简单地说,等式左侧的表达式将阻止索引的最佳使用,并可能将SQL优化器推向一个不太理想的计划。数据库引擎将完成比实际需要更多的工作,并且查询速度将[慢得多]。在极端情况下,他们甚至可以决定使用全表扫描。在这种情况下,您可以将其改写为:
AND mracct_ad1.code_valeur like 'MRAC%'
或:
和mracct\u ad1.code\u valeur>='MRAC'和mracct\u ad1.code\u valeur<'MRAD'
只是一个关于性能的说明。通常,您希望“重新表述”条件,如:
AND substr(mracct_ad1.code_valeur,1,4) = 'MRAC'
简单地说,等式左侧的表达式将阻止索引的最佳使用,并可能将SQL优化器推向一个不太理想的计划。数据库引擎将完成比实际需要更多的工作,并且查询速度将[慢得多]。在极端情况下,他们甚至可以决定使用全表扫描。在这种情况下,您可以将其改写为:
AND mracct_ad1.code_valeur like 'MRAC%'
或:
和mracct\u ad1.code\u valeur>='MRAC'和mracct\u ad1.code\u valeur<'MRAD'
这些代码行的作用完全相同。请解释这两个连接之间除了mouvement表的别名之外还有什么细微的不同。对不起,我更新了代码。这些代码行的作用完全相同。请解释除了移动表的别名之外,这两个连接之间还有什么细微的不同。对不起,我更新了代码。第二个代码很危险,因为NLS\u SORT
,不是吗?@Matthew是的,我同意你的看法。尽管第二个仍然是一个选项,但我倾向于避免它,因为在使用非典型排序规则时,它可能容易出错。虽然这是一个好主意,但将substr()
替换为like
似乎不太可能对具有30个左联接的查询产生明显的影响。第二个是有风险的,由于NLS\U排序
,不是吗?@Matthew是的,我同意你的看法。尽管第二个仍然是一个选项,但我倾向于避免它,因为在使用非典型排序规则时,它很容易出错。虽然这是一个好主意,但用like
替换substr()
似乎不太可能对具有30个左联接的查询产生明显的影响。它只是用不同的值进行相同的连接。@mouadtk。不,这将使用聚合结果的单个连接替换一组不同的连接。在这一点上,我把答案说得更清楚了。它只是用不同的值进行相同的连接。@mouadtk。不,这将使用聚合结果的单个连接替换一组不同的连接。在这一点上,我把答案说得更清楚了一点。