-1

我们可以调整下面的 oracle sql 查询吗?此查询需要大量时间从数据库中获取行。

SELECT T.ACCUMULATORS_INFO ACCU_INFO, T.SUBSCR_NO service_internal_id, 
T.SUBSCR_NO_RESETS service_internal_id_resets, T.*,T.MTR_TYPE_ID MTR_TYPE, 
T.ACCOUNT_NO account_internal_id, T.MTR_SUB_TYPE_ID MTR_SUB_TYPE, 
T.FILE_ID EXTRACT_FILE_ID, T.UNIT_TYPE_ID unit_type, RCV2.ISO_CODE PREV_SUBSCRIBER_CURRENCY, 
T.MTR_SOURCE_ID MTR_SOURCE, RCV1.ISO_CODE SUBSCRIBER_CURRENCY 
FROM  MTR T 
LEFT OUTER JOIN RATE_CURRENCY_REF RCV1 ON (T.CURRENCY_CODE = RCV1.CURRENCY_CODE) 
LEFT OUTER JOIN RATE_CURRENCY_REF RCV2 ON (T.PREV_CURRENCY_CODE = RCV2.CURRENCY_CODE) 
WHERE (T.CURRENCY_CODE IS NULL OR RCV1.service_version_id = ?) AND 
(T.PREV_CURRENCY_CODE IS NULL OR RCV2.service_version_id = ?) AND 
T.mod_date BETWEEN ? AND ? AND T.subscr_no = ? AND 
T.subscr_no_resets = ? 
ORDER BY T.mod_date DESC

问候,钱德拉

4

2 回答 2

0

在不知道模型和数据的情况下优化查询总是很困难,但这是我会尝试的。

您至少应该有一个索引 on
rate_currency_ref (currency_code, service_version_id )
,也许还有一个 on
mtr (mod_date, subscr_no, subscr_no_resets)

我还将调整查询以将附加条件放入LEFT JOINs 以获得更好的可读性(也许更好的优化)。

SELECT T.ACCUMULATORS_INFO ACCU_INFO, T.SUBSCR_NO service_internal_id, 
  T.SUBSCR_NO_RESETS service_internal_id_resets, T.*,T.MTR_TYPE_ID MTR_TYPE, 
  T.ACCOUNT_NO account_internal_id, T.MTR_SUB_TYPE_ID MTR_SUB_TYPE, 
  T.FILE_ID EXTRACT_FILE_ID, T.UNIT_TYPE_ID unit_type, RCV2.ISO_CODE PREV_SUBSCRIBER_CURRENCY, 
  T.MTR_SOURCE_ID MTR_SOURCE, RCV1.ISO_CODE SUBSCRIBER_CURRENCY 
FROM MTR T 
LEFT OUTER JOIN RATE_CURRENCY_REF RCV1
     ON (T.CURRENCY_CODE = RCV1.CURRENCY_CODE AND RCV1.service_version_id = ?)
LEFT OUTER JOIN RATE_CURRENCY_REF RCV2
     ON (T.PREV_CURRENCY_CODE = RCV2.CURRENCY_CODE AND RCV2.service_version_id = ?)
WHERE
  T.mod_date BETWEEN ? AND ? AND T.subscr_no = ? AND 
  T.subscr_no_resets = ? 
ORDER BY T.mod_date DESC
于 2012-07-12T10:12:31.090 回答
0

SQl 看起来很奇怪 ...(CURRENCY_CODE IS NULL OR service_version_id_RCV1 = ?)

无论如何,假设 SQL 在功能上是正确的并且尽管 'Peter' 建议了索引但性能不佳,我会调整和重写 SQL(使用子查询)以允许优化器选择更好的计划:-

SELECT tmp.*
FROM
  (SELECT T.ACCUMULATORS_INFO ACCU_INFO,
    T.SUBSCR_NO service_internal_id,
    T.SUBSCR_NO_RESETS service_internal_id_resets,
    T.*,
    T.MTR_TYPE_ID MTR_TYPE,
    T.ACCOUNT_NO account_internal_id,
    T.MTR_SUB_TYPE_ID MTR_SUB_TYPE,
    T.FILE_ID EXTRACT_FILE_ID,
    T.UNIT_TYPE_ID unit_type,
    RCV2.ISO_CODE PREV_SUBSCRIBER_CURRENCY,
    RCV2.service_version_id_RCV2,
    T.MTR_SOURCE_ID MTR_SOURCE,
    RCV1.ISO_CODE SUBSCRIBER_CURRENCY,
    RCV1.service_version_id_RCV1
  FROM MTR T
  LEFT OUTER JOIN RATE_CURRENCY_REF RCV1
  ON (T.CURRENCY_CODE = RCV1.CURRENCY_CODE)
  LEFT OUTER JOIN RATE_CURRENCY_REF RCV2
  ON (T.PREV_CURRENCY_CODE = RCV2.CURRENCY_CODE)
  WHERE T.mod_date BETWEEN ? AND ?
  AND T.subscr_no        = ?
  AND T.subscr_no_resets = ?
  ) tmp
WHERE (CURRENCY_CODE      IS NULL OR service_version_id_RCV1 = ?)
AND (PREV_CURRENCY_CODE   IS NULL OR service_version_id_RCV2 = ?)
ORDER BY mod_date DESC

我建议在 MTR 和 RATE_CURRENCY_REF 上保持以下索引:

  1. mtr (mod_date, subscr_no, subscr_no_resets)
  2. 地铁 (CURRENCY_CODE)
  3. 地铁 (PREV_CURRENCY_CODE)
  4. rate_currency_ref (currency_code)
于 2014-01-19T20:59:32.963 回答