Как выполнить настройку SQL на обновление ниже SQL - PullRequest
0 голосов
/ 06 июля 2018

каждый, Недавно я был вовлечен в одну задачу настройки SQL для оракула, У меня была очень сложная проблема, я думаю, я мог бы даже сказать, что был напуган этим вопросом, Я получаю отчет AWR от DBA, и кажется, что красная строка SQL от AMR нуждается в некоторой корректировке (я вставил этот SQL, как показано ниже, этот sql был в SP). Но я не знаю, что вызвало низкую производительность, кто угодно Можете помочь предложить некоторые решения или мысли по настройке SQL?

если вам нужны дополнительные доказательства из AWR, пожалуйста, дайте мне знать.

Заранее спасибо ...

    UPDATE tax_ratio tar
    SET
        ( ecm,
        esm,
        epm,
        ecam,
        update_dt,
        update_by ) = (
            SELECT
                nvl(src_t1.ecm,0) AS ecm,
                nvl(src_t1.esm,0) AS esm,
                nvl(src_t1.epm,0) AS epm,
                nvl(src_t1.ecam,0) AS ecam,
                SYSDATE,
                'ffee_user'
            FROM
                (
                    SELECT
                        city_code,
                        tax_type,
                        company_type,
                        taxpayer,
                        company_group,
                        company_tax_type,
                        SUM(new_tax_current_mth) /12 AS ecm,
                        SUM(new_tax_miss_current_mth) /12 AS esm,
                        SUM(new_tax_get_current_mth) /12 AS epm,
                        SUM(new_tax_special_current_mth) /12 AS ecam
                    FROM
                        tax_ratio
                    WHERE
                        city_code ='001'
                        AND   company_type ='typ_01'
                        AND   tax_mth <= add_months(TO_DATE('08-JUL-2015'),-3)
                        AND   tax_mth >= add_months(TO_DATE('08-JUL-2015'),-14)
                        AND   eff_date =TO_DATE('08-JUL-2015')
                        AND   tax_type = '00'
                    GROUP BY
                        city_code,
                        tax_type,
                        company_type,
                        taxpayer,
                        company_group,
                        company_tax_type
                    HAVING SUM(new_tax_current_mth) <> 0
                           OR SUM(new_tax_miss_current_mth) <> 0
                           OR SUM(new_tax_get_current_mth) <> 0
                           OR SUM(new_tax_special_current_mth) <> 0
                ) src_t1
            WHERE
                tar.city_code = src_t1.city_code
                AND   tar.tax_type = src_t1.tax_type
                AND   tar.company_type = src_t1.company_type
                AND   tar.taxpayer = src_t1.taxpayer
                AND   nvl(tar.company_group,'-99999') = nvl(src_t1.company_group,'-99999')
                AND   (
                    src_t1.ecm IS NOT NULL
                    OR    src_t1.esm IS NOT NULL
                    OR    src_t1.epm IS NOT NULL
                    OR    src_t1.ecam IS NOT NULL
                )
                AND   tar.tax_mth =TO_DATE('08-JUL-2015')
                AND   tar.company_tax_type = src_t1.company_tax_type
        )
WHERE
    tar.city_code ='001'
    AND   tar.company_type ='typ_01'
    AND   tar.tax_mth =TO_DATE('08-JUL-2015')
    AND   EXISTS (
        SELECT
            1
        FROM
            (
                SELECT
                    city_code,
                    tax_type,
                    company_type,
                    taxpayer,
                    company_group,
                    company_tax_type,
                    SUM(new_tax_current_mth) /12 AS ecm,
                    SUM(new_tax_miss_current_mth) /12 AS esm,
                    SUM(new_tax_get_current_mth) /12 AS epm,
                    SUM(new_tax_special_current_mth) /12 AS ecam
                FROM
                    tax_ratio
                WHERE
                    city_code ='001'
                    AND   company_type ='typ_01'
                    AND   tax_mth <= add_months(TO_DATE('08-JUL-2015'),-3)
                    AND   tax_mth >= add_months(TO_DATE('08-JUL-2015'),-14)
                    AND   eff_date =TO_DATE('08-Aug-2015')
                    AND   tax_type = '00'
                GROUP BY
                    city_code,
                    tax_type,
                    company_type,
                    taxpayer,
                    company_group,
                    company_tax_type
                HAVING SUM(new_tax_current_mth) <> 0
                       OR    SUM(new_tax_miss_current_mth) <> 0
                       OR    SUM(new_tax_get_current_mth) <> 0
                       OR    SUM(new_tax_special_current_mth) <> 0
            ) src_t1
        WHERE
            tar.city_code = src_t1.city_code
            AND   tar.tax_type = src_t1.tax_type
            AND   tar.company_type = src_t1.company_type
            AND   tar.taxpayer = src_t1.taxpayer
            AND   nvl(tar.company_group,'-99999') = nvl(src_t1.company_group,'-99999')
            AND   (
                src_t1.ecm IS NOT NULL
                OR    src_t1.esm IS NOT NULL
                OR    src_t1.epm IS NOT NULL
                OR    src_t1.ecam IS NOT NULL
            )
            AND   tar.tax_mth =TO_DATE('08-JUL-2015')
            AND   tar.company_tax_type = src_t1.company_tax_type
    )

enter image description here

add the EXPLAIN PLAN

PLAN HASH VALUE: 3650439649

----------------------------------------------------------------------------------------------------------------------
| ID  | OPERATION                                | NAME              | ROWS  | BYTES |TEMPSPC| COST (%CPU)| TIME     |
----------------------------------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT                         |                   |  1698 |   179K|       |  6169K  (1)| 00:08:02 |
|   1 |  UPDATE                                  | TAX_RATIO         |       |       |       |            |          |
|*  2 |   HASH JOIN RIGHT SEMI                   |                   |  1698 |   179K|       |   732K  (1)| 00:00:58 |
|   3 |    VIEW                                  |                   | 39251 |  1111K|       |   371K  (2)| 00:00:29 |
|*  4 |     FILTER                               |                   |       |       |       |            |          |
|   5 |      SORT GROUP BY                       |                   | 39251 |  2414K|   100M|   371K  (2)| 00:00:29 |
|*  6 |       TABLE ACCESS FULL                  | TAX_RATIO         |  1140K|    68M|       |   365K  (2)| 00:00:29 |
|*  7 |    TABLE ACCESS FULL                     | TAX_RATIO         |   207K|    15M|       |   361K  (1)| 00:00:29 |
|   8 |   VIEW                                   |                   |     1 |    81 |       |   484   (1)| 00:00:01 |
|*  9 |    FILTER                                |                   |       |       |       |            |          |
|  10 |     SORT GROUP BY                        |                   |     1 |    63 |       |   484   (1)| 00:00:01 |
|* 11 |      FILTER                              |                   |       |       |       |            |          |
|* 12 |       TABLE ACCESS BY INDEX ROWID BATCHED| TAX_RATIO         |     1 |    63 |       |   483   (0)| 00:00:01 |
|* 13 |        INDEX RANGE SCAN                  | TAX_RATIO_TAXPAYER_IDX |   544 |       |       |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------------

PREDICATE INFORMATION (IDENTIFIED BY OPERATION ID):
---------------------------------------------------

   2 - ACCESS("TAR"."CITY_CODE"="SRC_T1"."CITY_CODE" AND "TAR"."TAX_TYPE"="SRC_T1"."TAX_TYPE" AND 
              "TAR"."COMPANY_TYPE"="SRC_T1"."COMPANY_TYPE" AND "TAR"."TAXPAYER"="SRC_T1"."TAXPAYER" AND 
              NVL("TAR"."COMPANY_GROUP",'-99999')=NVL("SRC_T1"."COMPANY_GROUP",'-99999') AND "TAR"."COMPANY_TAX_TYPE"="SRC_T1"."COMPANY_TAX_TYPE")
   4 - FILTER((SUM("NEW_TAX_CURRENT_MTH")<>0 OR SUM("NEW_TAX_MISS_CURRENT_MTH")<>0 OR SUM("NEW_TAX_GET_CURRENT_MTH")<>0 OR SUM("NEW_TAX_SPECIAL_CURRENT_MTH")<>0) AND 
              (SUM("NEW_TAX_CURRENT_MTH")/12 IS NOT NULL OR SUM("NEW_TAX_MISS_CURRENT_MTH")/12 IS NOT NULL OR SUM("NEW_TAX_GET_CURRENT_MTH")/12 IS NOT NULL OR 
              SUM("NEW_TAX_SPECIAL_CURRENT_MTH")/12 IS NOT NULL))
   6 - FILTER("COMPANY_TYPE"='LIMIT' AND "TAX_TYPE"='00' AND "TAX_MTH">=TO_DATE(' 2017-03-31 00:00:00', 
              'SYYYY-MM-DD HH24:MI:SS') AND "TAX_MTH"<=TO_DATE(' 2018-02-28 00:00:00', 'SYYYY-MM-DD HH24:MI:SS') AND 
              "CITY_CODE"='001' AND "NEW_TAX_MISS_CURRENT_MTH"=TO_DATE(' 2200-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'))
   7 - FILTER("TAR"."TAX_MTH"=TO_DATE(' 2018-05-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS') AND 
              "TAR"."COMPANY_TYPE"='LIMIT' AND "TAR"."CITY_CODE"='001')
   9 - FILTER((SUM("NEW_TAX_CURRENT_MTH")<>0 OR SUM("NEW_TAX_MISS_CURRENT_MTH")<>0 OR SUM("NEW_TAX_GET_CURRENT_MTH")<>0 OR SUM("NEW_TAX_SPECIAL_CURRENT_MTH")<>0) AND 
              (SUM("NEW_TAX_CURRENT_MTH")/12 IS NOT NULL OR SUM("NEW_TAX_MISS_CURRENT_MTH")/12 IS NOT NULL OR SUM("NEW_TAX_GET_CURRENT_MTH")/12 IS NOT NULL OR 
              SUM("NEW_TAX_SPECIAL_CURRENT_MTH")/12 IS NOT NULL))
  11 - FILTER(:B1=TO_DATE(' 2018-05-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS') AND :B2='LIMIT' AND :B3='00' AND 
              :B4='001')
  12 - FILTER("COMPANY_TYPE"='LIMIT' AND "COMPANY_TAX_TYPE"=:B1 AND "TAX_TYPE"='00' AND "TAX_MTH">=TO_DATE(' 
              2017-03-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS') AND "TAX_MTH"<=TO_DATE(' 2018-02-28 00:00:00', 'SYYYY-MM-DD 
              HH24:MI:SS') AND NVL("COMPANY_GROUP",'-99999')=NVL(:B2,'-99999') AND "CITY_CODE"='001' AND "NEW_TAX_MISS_CURRENT_MTH"=TO_DATE(' 
              2200-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'))
  13 - ACCESS("TAXPAYER"=:B1)

1 Ответ

0 голосов
/ 06 июля 2018

Первое, что я попробую, - это использовать оператор MERGE вместо этого оператора UPDATE - это приходит на ум, потому что вы фактически повторяете подзапрос в предложении set в предложении where.

Я думаю, что ваше ОБНОВЛЕНИЕ может быть переписано примерно так:

MERGE INTO tax_ratio tgt
  USING (SELECT city_code,
                tax_type,
                company_type,
                taxpayer,
                company_group,
                company_tax_type,
                SUM(new_tax_current_mth) / 12 AS ecm,
                SUM(new_tax_miss_current_mth) / 12 AS esm,
                SUM(new_tax_get_current_mth) / 12 AS epm,
                SUM(new_tax_special_current_mth) / 12 AS ecam
         FROM   tax_ratio
         WHERE  city_code = '001'
         AND    company_type = 'typ_01'
         AND    tax_mth <= add_months(to_date('08-JUL-2015', 'dd-MON-yyyy', 'nls_date_language = english'), -3)
         AND    tax_mth >= add_months(to_date('08-JUL-2015', 'dd-MON-yyyy', 'nls_date_language = english'), -3)
         AND    eff_date = to_date('08-JUL-2015', 'dd-MON-yyyy', 'nls_date_language = english')
         AND    tax_type = '00'
         GROUP  BY city_code,
                   tax_type,
                   company_type,
                   taxpayer,
                   company_group,
                   company_tax_type
         HAVING SUM(new_tax_current_mth) <> 0 
                OR SUM(new_tax_miss_current_mth) <> 0
                OR SUM(new_tax_get_current_mth) <> 0
                OR SUM(new_tax_special_current_mth) <> 0)) src
  ON (tgt.city_code = src.city_code
      AND    tgt.tax_type = src.tax_type
      AND    tgt.company_type = src.company_type
      AND    tgt.taxpayer = src.taxpayer
      AND    NVL(tgt.company_group, '-99999') = NVL(src.company_group, '-99999')
      --AND    COALESCE(src.ecm, src.esm, src.epm, src.ecam) IS NOT NULL -- unnecessary, since your having clause excludes rows where all are null anyway
      AND    tgt.company_tax_type = src.company_tax_type)
WHEN MATCHED THEN
  UPDATE SET tgt.ecm = NVL(src.ecm, 0),
             tgt.esm = NVL(src.esm, 0),
             tgt.epm = NVL(src.epm, 0),
             tgt.ecam = NVL(src.ecam, 0),
             tgt.update_dt = SYSDATE,
             tgt.update_by = 'ffee_user')
  WHERE  tgt.tax_mth = to_date('08-JUL-2015', 'dd-MON-yyyy', 'nls_date_language = english');

Примечания:

  1. Я изменил to_dates(), чтобы включить маску формата (в противном случае, если ваш параметр NLS_DATE_FORMAT nls был изменен, to_date() потерпит неудачу), и, поскольку вы использовали «JUL» в качестве месяца, дополнительный третий параметр для сделать настройку nls для преобразования даты в строку как независимую (например, если для вашего параметра NLS NLS_DATE_FORMAT задано значение, для которого JUL не является допустимым коротким месяцем, to_date() завершится ошибкой, если этот третий параметр не был задавать). Вы можете избежать использования третьего параметра, передавая дату в виде чисел, например, to_date('05/07/2015', 'dd/mm/yyyy').
  2. Я изменил and ecm is not null and esm is not null and ..., чтобы использовать вместо него COALESCE, так как это возвращает первое ненулевое значение в списке. Таким образом, ваш чек становится and COALESCE(ecm, esm, ...) is not null.
  3. COALESCE на самом деле не требуется, поскольку ваше предложение HAVING эффективно исключает строки, в которых все значения равны NULL, а также 0.
  4. Предикаты, которые использовались для корреляции подзапроса, становятся условиями соединения между целевой таблицей и исходным подзапросом, что означает, что вам больше не нужен внешний запрос, который вы ранее имели в коррелированном подзапросе.
  5. Я переместил условие, чтобы обновлять только строки с указанным налоговым месяцем из предложения join в предложение WHERE раздела update. Я почти уверен, что это можно было бы оставить в предложении объединения, но я думаю, что намерение яснее, если оно будет включено в предложение WHERE обновления.

Я бы протестировал новый оператор MERGE, чтобы убедиться, что он работает правильно (или исправил его до тех пор, пока не сделал), а затем посмотрел, как это влияет на производительность.

Если бы он все еще появлялся как формулировка проблемы в AWR, то я бы еще больше посмотрел, как его настроить; возможно, обновлены / требуются дополнительные индексы, может быть материализованное представление и т. д.

...