Подзапрос замедляет обновление - PullRequest
0 голосов
/ 13 декабря 2018

Этот запрос ссылается на ~ 3M записей, и теперь для его запуска требуется абсолютный возраст.Данные берутся из электронной таблицы Excel с записями Cust / Invoices по строкам и ежемесячным значениям 2016 до текущих в столбцах.

Этот запрос проверяет наличие значения в том же месяце для одного и того же / разных продуктов и выводит 1, если его можно игнорировать, 0, если его следует учитывать для последующих запросов.

Я установил индекс для продукта, который учитывает начальные критерии, но это подзапрос, который абсолютно убивает это:

    UPDATE tbl_transactions a
    SET ProdInCust_Mnth_Same_SameProd_LowerVal =
        CASE WHEN
                (
                    SELECT COUNT(TransactionID) 
                    FROM tbl_transactions_tmp b 
                    WHERE 
                        b.TransactionID<>a.TransactionID AND
                        b.CustomerRef=a.CustomerRef AND
                        b.TransMonth=a.TransMonth AND
                        (
                            (
                                (b.Product='PLATINUM') AND
                                b.TransValue<0
                            )
                            OR                                  
                            (
                                a.TransValue=0 AND
                                (b.Product='PLATINUM' OR b.Product='GOLD' OR b.Product='SILVER') AND
                                b.TransValue<0
                            )
                            OR
                            (
                                a.TransValue<0 AND
                                (b.Product='PLATINUM' OR b.Product='GOLD') AND
                                ((b.TransValue=a.TransValue AND b.RowReference>a.RowReference) OR
                                    b.TransValue<a.TransValue
                                )
                            )
                        )
                )>0 THEN 1 ELSE 0 END   
    WHERE Product='GOLD';

EXPLAIN производит:

id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra
1   UPDATE  a   \N  index   IDX_tbl_transactions_Product    PRIMARY 8   \N  2828152 100 Using where
2   DEPENDENT SUBQUERY  b   \N  ref IX_Transactions_SP_ProcessTransAA   IX_Transactions_SP_ProcessTransAA   45  finance.a.CustomerRef,finance.a.TransMonth  1   20.7    Using where; Using index

Визуально он говорит, что это ПОЛНЫЙ ИНДЕКС СКАН, я предполагаю, что красный фон говорит о том, что это плохо.

Любые идеи, как я могу оптимизировать это дальше.

Ответы [ 3 ]

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

Можете ли вы попробовать что-то вроде ниже - используйте CTE или временную таблицу и оцените ожидаемый результат, используя регистр и где.Используйте это табличное значение при обновлении, вставьте соответствующий класс.Надеюсь, что это может помочь вам в создании запроса.Запрос может не дать точного результата, но может помочь вам в создании запроса.

UPDATE  a
    SET ProdInCust_Mnth_Same_SameProd_LowerVal = c.val
    tbl_transactions a
    JOIN cte c on a.TransactionID = c.TransactionID        
    --WHERE Product='GOLD';

WITH cte AS
(
SELECT b.TransactionID,  b.CustomerRef,b.TransMonth,b.TransValue, COUNT(TransactionID) ,
    case when  COUNT(TransactionID) > 0 then 1 else 0 END as val
                    FROM tbl_transactions_tmp b 
                    WHERE 
                       -- b.TransactionID<>a.TransactionID AND
                       -- b.CustomerRef=a.CustomerRef AND
                        b.TransMonth=a.TransMonth AND
                        (
                            (
                                (b.Product='PLATINUM') AND  b.TransValue<0
                            )
                            OR                                  
                            (
                                b.TransValue=0 AND
                                (b.Product='PLATINUM' OR b.Product='GOLD' OR b.Product='SILVER') AND
                                b.TransValue<0
                            )
                            OR
                            (
                                b.TransValue<0 AND
                                (b.Product='PLATINUM' OR b.Product='GOLD') AND
                                ((b.TransValue=a.TransValue AND b.RowReference>a.RowReference) OR
                                    b.TransValue<a.TransValue
                                )
                            )
                        )
                )
                group by b.CustomerRef
)
0 голосов
/ 14 декабря 2018

У вас есть этот составной индекс?Или более широкий индекс , начинающийся с с этими двумя столбцами?

INDEX(CustomerRef, TransMonth)   -- in either order

Можно ли рассчитывать информацию или ее часть один раз в месяц за предыдущий месяц?Сохранение этого в сводной таблице, а затем выполнение запросов к этой таблице может быть гораздо более быстрым способом.

Вы случайно не знаете, связаны ли вы с I / O или нет?Если вы привязаны к вводу / выводу, каково значение innodb_buffer_pool_size, сколько у вас ОЗУ и какой размер таблицы (ГБ)?

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

Попробуйте добавить индексы для всех полей, используемых в предложении WHERE подзапроса, к обеим таблицам и используйте EXISTS вместо COUNT:

UPDATE tbl_transactions a
SET ProdInCust_Mnth_Same_SameProd_LowerVal =
    CASE WHEN EXISTS
            (
                SELECT TransactionID
                FROM tbl_transactions_tmp b 
                WHERE 
                    b.TransactionID<>a.TransactionID AND
                    b.CustomerRef=a.CustomerRef AND
                    b.TransMonth=a.TransMonth AND
                    (
                        (
                            (b.Product='PLATINUM') AND
                            b.TransValue<0
                        )
                        OR                                  
                        (
                            a.TransValue=0 AND
                            (b.Product='PLATINUM' OR b.Product='GOLD' OR b.Product='SILVER') AND
                            b.TransValue<0
                        )
                        OR
                        (
                            a.TransValue<0 AND
                            (b.Product='PLATINUM' OR b.Product='GOLD') AND
                            ((b.TransValue=a.TransValue AND b.RowReference>a.RowReference) OR
                                b.TransValue<a.TransValue
                            )
                        )
                    )
            ) THEN 1 ELSE 0 END   
WHERE Product='GOLD';

ref: Является ли EXISTS более эффективным, чемCOUNT (*)> 0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...