SQL - улучшить производительность запросов NOT EXISTS

Есть ли способ улучшить производительность такого рода SQL-запросов:

INSERT
INTO ...
WHERE NOT EXISTS(Validation...)

Проблема в том, что когда у меня много данных в моей таблице (например, миллион строк), выполнение предложения WHERE NOT EXISTS выполняется очень медленно. Мне нужно выполнить эту проверку, потому что я не могу вставить повторяющиеся данные.

Я использую SQLServer 2005

Спасибо


person Melursus    schedule 16.02.2009    source источник
comment
Вы вставляете из одной таблицы в другую?   -  person achinda99    schedule 16.02.2009
comment
Да, но они форматируются по-разному. Например, в таблице A дата представляет собой целое число 20070102, а в таблице B таблица представляет собой дату и время.   -  person Melursus    schedule 17.02.2009
comment
обычно, если вы можете НЕ СУЩЕСТВОВАТЬ, то, вероятно, есть способ переключиться на использование EXISTS ... может потребоваться дополнительная временная таблица, но можно быть быстрее   -  person whytheq    schedule 15.08.2019


Ответы (7)


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

person cjk    schedule 16.02.2009

Вне всяких сомнений, вы могли бы попробовать что-нибудь вроде:

 TRUNCATE temptable
 INSERT INTO temptable ...
 INSERT INTO temptable ... 
 ...
 INSERT INTO realtable
 SELECT temptable.* FROM temptable
 LEFT JOIN realtable on realtable.key = temptable.key
 WHERE realtable.key is null
person Blorgbeard    schedule 16.02.2009
comment
В моих тестах в таблице с миллионами строк это было самым быстрым решением на сегодняшний день ... Вариант OP длится несколько минут, принятый ответ (ck) длится несколько минут, ваше решение длится 10 секунд (и я использую правильные индексы во всех решениях) - person David Espart; 02.08.2011

Попробуйте заменить NOT EXISTS левым внешним соединением, иногда это лучше работает в больших наборах данных.

person Otávio Décio    schedule 16.02.2009
comment
Забавно, я чаще находил обратное. EXISTS прекратит поиск при первом найденном совпадении, тогда как объединение сделает все возможные совпадения. Таким образом EXISTS должен быть быстрее. Я думаю. - person sfuqua; 17.02.2009
comment
Дело в том, что NOT EXISTS всегда будет вызывать сканирование таблицы, тогда как если вы будете осторожны с вашим объединением, вы можете работать исключительно с индексами. - person Otávio Décio; 17.02.2009
comment
ávio, я не думаю, что это правда, что NOT EXISTS всегда будет вызывать сканирование таблицы. См. Это сообщение: social .msdn.microsoft.com / Forums / en-US / transactsql / thread /. - person John M Gant; 11.11.2010

Обратите внимание на другой ответ по поводу индексации. NOT EXISTS обычно выполняется довольно быстро, если у вас хорошие индексы.

Но у меня были проблемы с производительностью с такими утверждениями, как вы описываете. Один метод, который я использовал, чтобы обойти это, - использовать временную таблицу для значений кандидатов, выполнить УДАЛИТЬ ИЗ ... ГДЕ СУЩЕСТВУЕТ (...), а затем вслепую ВСТАВИТЬ остаток. Конечно, внутри транзакции, чтобы избежать состояния гонки. Разделение запросов иногда позволяет оптимизатору выполнять свою работу, не запутавшись.

person dwc    schedule 16.02.2009

Мне нравится Outer Apply ...

вместо:

from t1
where not exists (select 1 from t2 where t1.something=t2.something)

Я буду использовать:

from t1
outer apply (
    select top 1 1 as found from t2 where t1.something=t2.something
) t2f
where t2f.found is null
person b_levitt    schedule 30.09.2019

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

Еще вы можете попробовать поставить DELETE InsertTable FROM InsertTable INNER JOIN ExistingTable ON <Validation criteria> перед вставкой. Однако ваш пробег может отличаться.

person hova    schedule 16.02.2009

insert into customers 
select * 
from newcustomers 
where customerid not in (select customerid 
                         from customers)

..могут быть более эффективными. Как говорили другие, убедитесь, что у вас есть индексы для любых полей поиска.

person SqlACID    schedule 16.02.2009