Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在同一个表上具有多个联接的Oracle复杂查询_Sql_Oracle_Query Optimization_Sql Tuning - Fatal编程技术网

Sql 在同一个表上具有多个联接的Oracle复杂查询

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

我正在处理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_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。不,这将使用聚合结果的单个连接替换一组不同的连接。在这一点上,我把答案说得更清楚了一点。