我意识到以下使用DISTINCT
的SQL对于性能而言是一件坏事。
但是,如果不包含该行,它将返回太多行(由于Instrument
和Party
表之间的一对多关系)。
我已经搜索了互联网,看到了一些摆脱DISTINCT
的建议,但老实说,我不知道最好的解决方案是什么。
能否请您提供一些建议,以改进此SQL并确保每个工具仅返回一行(而不是每个工具返回多行)?
仅供参考-我认为有些事情是性能建议:
摆脱掉容易完成的IN语句
用GROUP BY代替DISTINCT,这真的可以提高性能吗?
也许在不带DISTINCT的大SQL周围进行包含DISTINCT的外部SELECT。我的想法是,DISTINCT将在比INSTRUMENT表中的1M ++行小的子集上执行。
我的查询:
select *
from
(
SELECT DISTINCT
I.UOID,
I.INSTRUMENT_ID,
I.STATUS,
I.A_ACTIVITY_ORIG,
I.A_CURRENCY,
I.A_OPER_BK_ORG_ORIG,
I.A_POSITION_ACTIVE,
I.A_PRODUCT,
I.A_PRODUCT_TYPE,
I.A_TERMS_ACTIVE,
I.CURR_COI,
I.BOUT_COI,
I.A_CUST_RELATIONSHP,
I.DATE_START,
I.DATE_END,
I.CLIB_COI,
I.CLIB_BASE,
I.BLIB_COI,
I.BLIB_BASE,
I.BOUT_BASE,
I.AVAL_COI,
I.SEQUENCE_NUM,
I.AVAL_BASE,
I.MAXU_COI,
I.MAXU_BASE,
I.A_CURRENCY_BASE,I.A_CLIENT_BANK,
I.A_PRODUCT_CATEGORY,
I.A_ASSIGNMENT_ACTV,
I.A_RELATED_ACTIVITY,
C.CUSTOMER_ID,
C.SHORT_NAME
FROM instrument I
INNER JOIN PARTY P ON P.A_INSTRUMENT = I.UOID
INNER JOIN CUSTOMER C ON P.A_CUSTOMER = C.UOID AND C.CUSTOMER_ID = :customerId
WHERE (I.STATUS <> 'TMP')
AND (I.A_CLIENT_BANK = :clientBank)
AND I.A_PRODUCT_CATEGORY <> 'CM'
AND I.STATUS NOT IN ( 'CAN','CLO','DEA','LIQ')
)
where rownum <= :maxSize;
答案 0 :(得分:0)
您要寻找的客户与一方的乐器有关。由于客户也与多方相关,因此他们可以多次与同一工具相关。您可以使用IN
或EXISTS
子句来获取发生在客户方中的所有工具,但您也想从客户表中进行选择。因此,您想加入,这是使用DISTINCT
真正有意义的少数情况之一。
关于您的想法:
摆脱容易的IN语句
我认为您没有理由这么做。您是说要用多个IN
替换OR
吗?这样只会降低查询的可读性,并在内部执行相同的操作。
用GROUP BY代替DISTINCT真的可以提高性能吗?
不要。它做同样的事情,但是会降低可读性。 GROUP BY
用于汇总。由于您没有使用任何聚合函数,因此请使用DISTINCT
。执行计划应该完全相同。
也许在不带DISTINCT的大SQL周围进行包含DISTINCT的外部SELECT。我的想法是,DISTINCT将在比INSTRUMENT表中的1M ++行小的子集上执行。
否,步骤将相同:找到客户的参与方,找到符合您条件的这些参与方的工具,仅显示其中一些。
除使用索引外,我看不出有什么可以改善您的查询的。我不知道,最好是通过交易双方与客户达成交易,反之亦然,因此我将为这两种情况创建索引:
create index idxc1 on customer( customer_id, uoid );
create index idxp1 on party ( a_customer, a_instrument );
create index idxi1 on instrument ( uoid, a_client_bank, status, a_product_category );
create index idxi2 on instrument ( a_client_bank, status, a_product_category, uoid );
create index idxp2 on party ( a_instrument, a_customer );
create index idxc2 on customer( uoid, customer_id );
然后运行查询或检索说明计划,查看实际使用的索引并删除其他索引。