2012-01-02 3 views
1

Я пытаюсь обнаружить некоторые сломанные записи в базе данных MS-SQL.Каков самый быстрый способ определить несогласованные записи между двумя таблицами?

В упрощенном примере scenerio это:

У меня есть 2 таблицы, просто говоря:

  • Table_1: Id, дата, OpId

  • Table_2: Дата, OpId , EventName

И у меня есть это правило: если в таблице есть запись N не менее 1 строки должно существовать в таблице_2 для Table_1.Date и Table.OpId.

Если в таблице_1 есть строка, и если в таблице нет строки, соответствующей этой строке, ТОГДА есть сломанные данные - независимо от причины.

Чтобы узнать неверные данные, я использую:

SELECT * 
FROM table_1 t1 
LEFT JOIN table_2 t2 ON t1.Date = t2.Date AND t1.OpId = t2.OpId 
WHERE t2.OpId IS NULL -- So, if there is no 
--       matching row in table_2 then this is a mistake 

Но это занимает слишком много времени, чтобы выполнить запрос завершен.

Может ли быть более быстрый или лучший способ приблизиться к аналогичным сценариям?

ответ

6

Для анти полу присоединиться NOT EXISTS в SQL Server, как правило, лучше, чем или равный по производительности другие варианты (NOT IN, OUTER JOIN ... NULL, EXCEPT)

SELECT * 
FROM table_1 t1 
WHERE NOT EXISTS (SELECT * 
        FROM table_2 t2 
        WHERE t1.Date = t2.Date 
          AND t1.OpId = t2.OpId) 

См Left outer join vs NOT EXISTS. Однако, возможно, вам не хватает полезного индекса.

+0

Wow! Это сработало! Почему в этом запросе гораздо быстрее? – pencilCake

+0

ЗА ИСКЛЮЧЕНИЕМ И НЕ СУЩЕСТВУЮТ. И лучшей ссылкой является http://explainextended.com/2009/09/15/not-in-vs-not-exists-vs-left-join-is-null-sql-server/ – gbn

+0

@gbn - 'EXCEPT' полезно только в том случае, если вам не нужны дополнительные столбцы из первой таблицы, поэтому «NOT EXISTS» является хорошим выбором по умолчанию. (Я сказал «лучше или равно») –

1

Если вы используете правильную индексацию не имеет ничего общего с ним (можно использовать NOT EXISTS вместо LEFT JOIN будет немного быстрее),

НО

если Table_1 это имеет относительно небольшой объем данных, и нет каких-либо функциональных кнопок или другой такой вещи, и это процедура время один, то вы можете использовать трюк, как это падение некорректные строки:

SELECT table_1.* 
INTO tempTable 
FROM table_1 t1 
WHERE EXISTS(SELECT * FROM table_1 t1 WHERE t1.Date = t2.Date AND t1.OpId = t2.OpId) 

drop table Table_1 

exec sp_rename 'tempTable', 'Table_1' 

Это может быстрее

+0

Извините, изменили ошибочные имена таблиц –

+0

Это определенно быстрее Олег; - Я проверю статью, которую Мартин рекомендовал. Я действительно хочу понять основную причину этой разницы в скорости. – pencilCake

+2

Его довольно просто - ПРИСОЕДИНЯЙТЕСЬ НАЙТИ ВСЕ строки в таблице 1, соответствующие строкам в таблице2, но НЕ СУЩЕСТВУЕТ достаточно, чтобы найти ПЕРВОЕ пересечение, чтобы, наконец, пропустить строку и остальную часть поиска в виде соединения и перейти к следующей строке. И когда вы используете NOT EXISTS, оптимизатор выбирает лучший индекс, который он хочет, вместо SELECT * ... LEFT JOIN, потому что в NOT EXISTS его не касается конкретных столбцов в таблице2, а в select-left join - он делает - и это ограничивает его или предотвращает использование соответствующих индексов –

Смежные вопросы