Повторная вставка строк с идентичными столбцами - PullRequest
3 голосов
/ 18 мая 2011

Я реализую очередь в SQL Server (2008 R2), содержащую задания, которые должны быть выполнены. По завершении задание перемещается в таблицу истории, устанавливая флаг успеха или сбоя. Элементы в таблице очередей имеют столбец идентификации в качестве первичного ключа. Очередь истории имеет комбо этого идентификатора и метку времени в виде PK.

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

Я вижу два возможных решения:

1) Использовать IDENTITY_INSERT:

SET IDENTITY_INSERT TableName ON

-- Move from history to live queue

SET IDENTITY_INSERT TableName OFF

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

Я не вижу каких-либо реальных проблем с 2, кроме того, что он грязный, возможно, плохой работы и что он заставляет мою невротическую кожу ползать ...

Вариант 1 Мне нравится, но я недостаточно хорошо знаю последствия. Как это будет работать? И я знаю, что одновременное выполнение двух таблиц приведет к краху и сбою. Что произойдет, если два потока сделают это с одной и той же таблицей одновременно?

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

Есть мысли о том, какой вариант лучше или есть лучший способ?

Ответы [ 4 ]

1 голос
/ 18 мая 2011

Я бы выбрал вариант 1 - Использовать IDENTITY_INSERT

SET IDENTITY_INSERT TableName ON

-- Move from history to live queue

SET IDENTITY_INSERT TableName OFF

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

0 голосов
/ 18 мая 2011

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

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

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

0 голосов
/ 18 мая 2011

Предполагая, что столбец Идентификация очереди является тем, который назначает «Идентификаторы заданий», я думаю, что самое простое решение - добавить новый обнуляемый столбец «OriginalJobID», потенциально с FK, указывающим на таблицу истории. Затем, когда вы перезапускаете задание, дайте ему возможность получить новый идентификатор при добавлении в очередь, но сохраните ссылку на исходное задание в этом новом столбце.

Чтобы ответить «или эту технику следует использовать только для пакетной вставки данных один раз в синюю луну», я бы сказал, да, определенно, это именно то, для чего оно нужно.


Упс, @Damien_The_Unbeliever прав, я забыл, что настройка IDENTITY_INSERT для каждого соединения. Было бы сложно получить реальную проблему с подходом вставки идентификаторов (было бы что-то вроде MARS, я думаю, или плохая обработка ошибок). Тем не менее, я думаю, что пытаться повторно использовать идентификаторы - ошибка!

0 голосов
/ 18 мая 2011

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

...