Рекомендации для фильтров строк на основе времени

Применимо к:SQL Server

Пользователям приложений часто требуется подмножество данных из таблицы, относящихся к определенному времени. Например, менеджеру по продажам могут понадобиться данные заказов за последнюю неделю, или планировщику событий требуются данные о событиях на следующей неделе. Во многих случаях приложения используют для этого запросы, содержащие функцию GETDATE() . Рассмотрим следующую инструкцию фильтра строк:

WHERE SalesPersonID = CONVERT(INT,HOST_NAME()) AND OrderDate >= (GETDATE()-6)  

С фильтром такого типа обычно подразумевается, что при выполнении агента слияния происходят две вещи: строки, удовлетворяющие условиям фильтра, реплицируются в подписчиках, а строки, больше не удовлетворяющие условию, удаляются в подписчиках. Дополнительные сведения о параметрах фильтрации с использованием HOST_NAME() см. в статье Параметризованные фильтры строк. Но репликация слиянием реплицирует и удаляет только данные, изменившиеся с момента последней синхронизации, независимо от того, как определяется фильтр строк для этих данных.

Чтобы репликация слиянием могла обработать строку, данные в строке должны удовлетворять условиям фильтра строк и должны измениться с момента последней синхронизации. В случае таблицы SalesOrderHeader при вставке строки вводится OrderDate . Строки правильно реплицируются на подписчик, потому что вставка является изменением данных. Однако если в подписчике имеются строки, больше не удовлетворяющие условиям фильтра (заказы старше семи дней), они не удаляются из подписчика, если не были обновлены по какой-то другой причине.

Пример планировщика событий делает более понятной проблему этого типа фильтрации. Рассмотрим следующий фильтр для таблицы Events :

WHERE EventCoordID = CONVERT(INT,HOST_NAME()) AND EventDate <= (GETDATE()+6)  

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

Кроме того, в зависимости от настройки публикации репликация слиянием вычисляет фильтры в разное время:

  • Если в публикации используются предварительно вычисляемые секции (по умолчанию), фильтры вычисляются при вставке или обновлении строк.

  • Если в публикации не используются предварительно вычисляемые секции, фильтры вычисляются при выполнении агента слияния.

Дополнительные сведения о предварительно вычисляемых секциях см. в статье Оптимизация производительности параметризованного фильтра с помощью предварительно вычисляемых секций. Время вычисления фильтра влияет на то, какие данные удовлетворяют условиям фильтра. Например, если в публикации используются предварительно вычисляемые секции, а данные синхронизируются каждые два дня, подмножество данных для менеджера по продажам может включать строки на два дня старше, чем ожидалось.

Рекомендации по использованию фильтров строк на основе времени

Следующий метод обеспечивает простой и надежный подход к фильтрации, основанной на времени:

  • Добавьте в таблицу столбец с типом данных bit. Он используется для указания, должна ли реплицироваться строка.

  • Используйте фильтр строк, который ссылается на добавленный столбец, а не на временной столбец.

  • Создайте задание агента SQL Server (или задание, запланированное с помощью другого механизма), которое будет обновлять этот столбец перед запуском агента слияния.

Такой подход решает недостатки использования функции GETDATE() или другого метода на основе времени и помогает избежать необходимости определять время вычисления фильтров для секций. Рассмотрим следующий пример для таблицы Events :

EventID EventName EventCoordID EventDate Репликация
1 Прием 112 2006-10-04 1
2 Обед 112 2006-10-10 0
3 Вечеринка 112 2006-10-11 0
4 Свадьба 112 2006-10-12 0

Фильтр строк для этой таблицы будет выглядеть следующим образом:

WHERE EventCoordID = CONVERT(INT,HOST_NAME()) AND Replicate = 1  

Задание агента SQL Server может выполнять инструкции Transact-SQL, аналогичные приведенным ниже перед выполнением каждого агента слияния:

UPDATE Events SET Replicate = 0 WHERE Replicate = 1  
GO  
UPDATE Events SET Replicate = 1 WHERE EventDate <= GETDATE()+6  
GO  

Первая строка сбрасывает столбец Replicate на 0, а вторая устанавливает значение столбца на 1 для событий, которые произойдут в течение следующих семи дней. Если эта инструкция Transact-SQL выполняется 10.07.2006, таблица обновляется следующим образом:

EventID EventName EventCoordID EventDate Репликация
1 Прием 112 2006-10-04 0
2 Обед 112 2006-10-10 1
3 Вечеринка 112 2006-10-11 1
4 Свадьба 112 2006-10-12 1

События следующей недели теперь помечены как готовые к репликации. При следующем запуске агента слияния для подписки, которую использует координатор событий 112, строки 2, 3 и 4 будут загружены на подписчик, а строка 1 будет из него удалена.

См. также

GETDATE (Transact-SQL)
Реализация заданий
Параметризованные фильтры строк