Эффективный способ создания последовательных чисел в федерациях SQL Azure - PullRequest
6 голосов
/ 10 марта 2012

Учитывая, что SQL Azure Federations не поддерживает свойство IDENTITY или SEQUENCE, каков будет эффективный способ создания последовательных чисел при вставке записей?

Например, для таблицы с этими столбцами:

CREATE TABLE [dbo].[Orders] (
    [TenantId] [uniqueidentifier] NOT NULL,
    [OrderId] [uniqueidentifier] NOT NULL,
    [OrderNumber] [int] NOT NULL
    CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED (
        [TenantId] ASC,
        [OrderId] ASC
    )
) FEDERATED ON ([FederationKey] = [TenantId])

для каждого заказа, вставленного для данного арендатора, OrderId должен быть увеличен. Например, для арендатора A OrderId будет 1, 2, 3 ..., а для арендатора B OrderId также будет 1, 2, 3 ... в независимой последовательности. В идеале не должно быть пробелов.

TenantId и OrderId являются компонентами первичного ключа. Их значения устанавливаются приложением, и они не связаны с вопросом генерации последовательностей; только OrderId имеет порядковый номер с деловым значением. Кроме того, TenantId является ключом распространения федерации.

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

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

Ответы [ 2 ]

2 голосов
/ 12 марта 2012

не уверен, сколько усилий потребуется, чтобы соответствовать вашему сценарию, но посмотрите на это и посмотрите, сможете ли вы его настроить: SnowMaker - генератор уникальных идентификаторов для Azure (или любой другой среды облачного хостинга))

2 голосов
/ 12 марта 2012

Вот еще 2 идеи.

Подход может состоять в том, чтобы отдельный процесс обновил это поле, чтобы сделать его асинхронным, если это возможно для вашего бизнес-сценария.Для этого подхода необходимо, чтобы поле OrderNumber принимало значения NULL.Чтобы узнать, какой Order пришел первым, чтобы он получил правильный OrderNumber, я бы также добавил поле InsertedDate.Асинхронная обработка становится более сложной, если у вас есть несколько рабочих ролей, выполняющих эту обязанность для избыточности, и в этом случае вам нужно будет, чтобы каждый процесс назначил себе записи, над которыми он работает (поэтому вам также необходимо поле OwnedBy), добавьте тест параллелизма во время выполнения.ОБНОВЛЕНИЕ, чтобы гарантировать, что каждый процесс выполняется на своих собственных записях, и срок действия назначения записей истекает (поэтому вам также необходимо поле AssignedOn), если процесс завершается сбоем, чтобы он не оставил сирот.Не совсем тривиально ...

И тогда у вас есть подход бедного человека ... который, когда звезды выстраиваются достаточно хорошо, может быть всем, что вам нужно.Если вы хотите использовать оптимистический подход к параллелизму, попробуйте использовать следующий номер во время вставки (сначала выберите MAX OrderNumber для заданных TenantId и OrderId), затем выполните вставку.Если вставка не удалась (потому что вы добавили уникальный индекс для TenantId, OrderNumber для этой цели), просто добавьте 1 к OrderNumber.Реальная проблема здесь заключается в частоте повторных попыток и вероятности неудачи такого подхода.Если у вас относительно упрощенный бизнес-процесс, он может никогда не потерпеть неудачу;однако если вы постоянно добавляете заказы из нескольких путей, это может быть неприемлемым подходом.

...