SQL改进

时间:2018-11-08 06:00:02

标签: sql oracle

我意识到以下使用DISTINCT的SQL对于性能而言是一件坏事。

但是,如果不包含该行,它将返回太多行(由于InstrumentParty表之间的一对多关系)。

我已经搜索了互联网,看到了一些摆脱DISTINCT的建议,但老实说,我不知道最好的解决方案是什么。

能否请您提供一些建议,以改进此SQL并确保每个工具仅返回一行(而不是每个工具返回多行)?

仅供参考-我认为有些事情是性能建议:

  1. 摆脱掉容易完成的IN语句

  2. 用GROUP BY代替DISTINCT,这真的可以提高性能吗?

  3. 也许在不带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;

1 个答案:

答案 0 :(得分:0)

您要寻找的客户与一方的乐器有关。由于客户也与多方相关,因此他们可以多次与同一工具相关。您可以使用INEXISTS子句来获取发生在客户方中的所有工具,但您也想从客户表中进行选择。因此,您想加入,这是使用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 );

然后运行查询或检索说明计划,查看实际使用的索引并删除其他索引。