Создать SQL индексы для скорости - PullRequest
0 голосов
/ 07 января 2020

Я удаляю дубликаты из таблицы со столбцом transaction_id и столбцом last_modified_date (см. Ниже запроса). Идея состоит в том, что у меня должна быть одна запись на transaction_id, поэтому мне нужно удалить дубликаты, сохранив последнюю измененную запись для данного transaction_id.

Запрос работает, но медленный.

Вопрос в том, какой индекс я должен создать, чтобы ускорить время выполнения запроса?

With CTE_Duplicates as
(
   select 
       transaction_id, 
       row_number() over (partition by transaction_id order by last_modified_date desc) rownumber 
   from 
       TRANSACTIONS 
)  
delete from CTE_Duplicates 
where rownumber != 1;  

Спасибо!

Vald

Ответы [ 3 ]

1 голос
/ 07 января 2020

Для вашей версии запроса:

With CTE_Duplicates as (
    select t.*,
           row_number() over (partition by transaction_id order by last_modified_date desc) as rownumber
    from TRANSACTIONS
   )
delete from CTE_Duplicates
    where rownumber > 1;

Требуется индекс для (transaction_id, last_modified_date desc). Однако с тем же индексом может быть быстрее сформулировать запрос следующим образом:

delete t from transactions t
    where t.last_modified_date = (select max(t2.last_modified_date)
                                  from transactions t2
                                  where t2.transaction_id = t.transaction_id
                                 );

Все это говорит о том, что ваш запрос будет довольно дорогим, если будет удалено много строк («многие» могут даже быть несколько процентов). В этом случае решение для временной таблицы может быть лучше:

select t.*
into temp_transactions
from transactions t
where t.last_modified_date = (select max(t2.last_modified_date)
                              from transactions t2
                              where t2.transaction_id = t.transaction_id
                             );

truncation table temp_transactions;  -- backup first!

insert into transactions
    select *
    from temp_transactions;

Конечно, логика c будет более сложной, если у вас есть идентификаторы столбцов или триггеры, которые устанавливают значения в таблице.

0 голосов
/ 07 января 2020

Независимо от того, какое решение вы выберете, вероятно, лучшее, что вы можете сделать, - это добавить составной индекс для (action_id, last_modified_date). После этого я бы go использовал бы агрегатную функцию по сравнению с оконной (учитывая их способность разбивать и упорядочивать, я не уверен, насколько хорошо они воспользуются идеальным индексом) ...

; WITH keepers AS (
   SELECT transaction_id, MAX(last_modified_date) AS last_modified_date
   FROM transactions 
   GROUP BY transaction_id
)
DELETE t 
FROM transactions AS t
LEFT JOIN keepers AS k
   ON t.transaction_id = k.transaction_id 
   AND t.last_modified_date = k.last_modified_date
WHERE k.transaction_id IS NULL
;
0 голосов
/ 07 января 2020

Для этого запроса:

with CTE_Duplicates as (
    select 
        transaction_id, 
        row_number() 
            over(partition by transaction_id order by last_modified_date desc ) rownumber 
    from TRANSACTIONS 
) 
delete from CTE_Duplicates where rownumber!=1;

Вы просто хотите составной индекс для (transaction_id, last_modified_date).

create index idx_transactions_dup on transactions(transaction_id, last_modified_date);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...