приведенный ниже оператор выбора занимает много времени - PullRequest
0 голосов
/ 30 декабря 2018

Это select утверждение занимает много времени, после моего расследования я обнаружил, что проблема подзапрос, хранимая процедура, пожалуйста, я ценю вашу помощь.

SELECT DISTINCT
    COKE_CHQ_NUMBER,
    COKE_PAY_SUPPLIER
FROM
    apps.Q_COKE_AP_CHECKS_SIGN_STATUS_V
WHERE 
    plan_id = 40192
    AND COKE_SIGNATURE__A = 'YES'
    AND COKE_SIGNATURE__B = 'YES'
    AND COKE_AUDIT = 'YES'
    AND COKE_CHQ_NUMBER NOT IN (SELECT DISTINCT COKE_CHQ_NUMBER_DELIVER
                                FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V
                                WHERE UPPER(COKE_CHQ_NUMBER_DELIVER_STATUS) <> 'DELIVERED')
    AND COKE_CHQ_NUMBER NOT IN (SELECT COKE_CHQ_NUMBER_DELIVER
                                FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V)

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

ищет ваш код .. кажется, у вас есть избыточность, когда условие, в котором второе NOT IN подразумевает первые шаги, чтобы вы могли избежать

, вы также можете преобразовать свое предложение NOT IN в предложение MINUS .. присоединиться к тому же запросус INNER присоединиться к вам не в подзапросе

и, наконец, будьте осторожны, у вас есть правильный составной индекс для таблицы

Q_COKE_AP_CHECKS_SIGN_STATUS_V 
cols (plan_id,COKE_SIGNATURE__A , COKE_SIGNATURE__B, COKE_AUDIT, COKE_CHQ_NUMBER, COKE_PAY_SUPPLIER)


SELECT DISTINCT
    COKE_CHQ_NUMBER,
    COKE_PAY_SUPPLIER
FROM
    apps.Q_COKE_AP_CHECKS_SIGN_STATUS_V
WHERE 
    plan_id = 40192
    AND COKE_SIGNATURE__A = 'YES'
    AND COKE_SIGNATURE__B = 'YES'
    AND COKE_AUDIT = 'YES'

MINUS 


SELECT DISTINCT
    COKE_CHQ_NUMBER,
    COKE_PAY_SUPPLIER
FROM  apps.Q_COKE_AP_CHECKS_SIGN_STATUS_V
INNER JOIN (
    SELECT COKE_CHQ_NUMBER_DELIVER
    FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V
) T ON T.COKE_CHQ_NUMBER_DELIVER = apps.Q_COKE_AP_CHECKS_SIGN_STATUS_V
WHERE 
    plan_id = 40192
    AND COKE_SIGNATURE__A = 'YES'
    AND COKE_SIGNATURE__B = 'YES'
    AND COKE_AUDIT = 'YES'
0 голосов
/ 31 декабря 2018

Что ж, в вашем операторе SELECT есть несколько проблем, на которые следует обратить внимание:

Сначала давайте посмотрим на это условие:

COKE_CHQ_NUMBER NOT IN (SELECT DISTINCT COKE_CHQ_NUMBER_DELIVER
                         FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V
                        WHERE UPPER(COKE_CHQ_NUMBER_DELIVER_STATUS) <> 'DELIVERED')

Сначала вы выберете DISTINCT проверить номера с помощьюстатус не доставлен, тогда вы говорите, что не хотите этого.Вместо того, чтобы говорить Я не хочу, чтобы не доставлено гораздо удобнее сказать: Я хочу доставить единиц.Однако это на самом деле не проблема, а скорее сделает ваш SELECT легче для чтения и понимания.

Во-вторых, давайте посмотрим на ваше второе условие проверки:

COKE_CHQ_NUMBER NOT IN (SELECT COKE_CHQ_NUMBER_DELIVER
                         FROM apps.Q_COKE_AP_CHECKS_DELIVERY_ST_V)

Здесь вы хотите исключить всечеки, которые имеют запись в Q_COKE_AP_CHECKS_DELIVERY_ST_V.Это делает ваше первое DISTINCT условие избыточным, поскольку любые проверочные номера будут возвращены этим вторым вашим условием.Я не знаю, достаточно ли умен движок Oracle SQL, чтобы сработать с этой избыточностью, но это может привести к вашей медлительности, так как для выполнения SELECT может потребоваться больше времени

В дополнение к этому, если у вас их еще нет, ярекомендовал бы добавить следующие индексы:

CREATE INDEX index_1 ON q_coke_ap_checks_sign_status_v(coke_chq_number, coke_pay_supplier);
CREATE INDEX index_2 ON q_coke_ap_checks_sign_status_v(plan_id, coke_signature__a, coke_signature__b, coke_audit);
CREATE INDEX index_3 ON q_coke_ap_checks_delivery_st_v(coke_chq_number_deliver);

Я назвал index_1,2,3 для легкого чтения, очевидно, не хорошего соглашения об именах.

С этим на месте ваш выбор должен быть оптимизированчтобы получить ваши данные в приемлемом исполнении.Но, конечно, все зависит от размера и распределения ваших данных, которые трудно контролировать без проведения специального анализа данных.

...