2012-03-10 12 views
6

Considerando che le federazioni SQL Azure non supportano la proprietà IDENTITY o SEQUENCE, quale sarebbe un modo efficiente per generare numeri sequenziali durante l'inserimento di record?Modo efficiente di generare numeri sequenziali su federazioni SQL Azure

Ad esempio, data una tabella con queste colonne:

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]) 

per ogni ordine inserito, per un determinato conduttore, l'OrderId deve essere incrementata. Ad esempio, per un decente A OrderId sarebbe 1, 2, 3 ... e per l'inquilino B OrderId sarebbe anche 1, 2, 3 ... in una sequenza indipendente. Idealmente non dovrebbero esserci lacune.

TenantId e OrderId sono componenti della chiave primaria. I loro valori sono impostati dall'applicazione e non sono correlati al problema della generazione di sequenze; solo OrderId ha il numero sequenziale con significato commerciale. Inoltre, TenantId è la chiave di distribuzione della federazione.

This MSDN Blog article descrive nell'opzione 1 un approccio di avere una tabella contenente le sequenze e l'utilizzo di una stored procedure in una transazione segregata per incrementare le sequenze. Ogni inquilino avrebbe un record su questa tabella tenendo l'ultimo valore utilizzato della sequenza.

Questo sarebbe l'approccio ottimale considerando scalabilità, contesa, blocco delle risorse? Qualche altro trucco utile, considerando i limiti delle federazioni SQL Azure?

risposta

2

Qui ci sono 2 idee aggiuntive.

Un approccio sarebbe avere un aggiornamento di processo separato in quel campo per renderlo asincrono, se questo è qualcosa possibile per il proprio scenario aziendale. È necessario che il campo OrderNumber accetti valori NULL per questo approccio. Per sapere quale Ordine è arrivato per primo, in modo da ottenere il Numero Ordine corretto, aggiungerei anche un campo InserisciData. L'elaborazione asincrona diventa più complessa se si hanno più ruoli di lavoro che eseguono questo dovere per la ridondanza, nel qual caso sarà necessario che ogni processo assegni a sé i record su cui sta lavorando (quindi è necessario anche un campo OwnedBy), aggiungere un test di concorrenza durante l'AGGIORNAMENTO per garantire che ciascun processo sia in esecuzione sui propri record e che l'assegnazione dei record sia scaduta (quindi è necessario anche un campo AssignedOn) se il processo si blocca in modo tale da non lasciare orfani. Non proprio banale ...

E poi l'approccio del povero uomo ... che quando le stelle si allineano abbastanza bene può essere tutto ciò che serve. Se si desidera avere un approccio di concorrenza ottimistico, provare a utilizzare il numero successivo durante l'inserimento (selezionare prima il numero di ordine MAX per un determinato TenantId e OrderId), quindi eseguire l'inserimento. Se l'inserimento fallisce (perché hai aggiunto un indice Unique su TenantId, OrderNumber per quello scopo), aggiungi 1 al numero dell'ordine. Il vero problema qui è la frequenza dei tentativi e la probabilità che questo approccio fallisca. Se si dispone di un processo aziendale relativamente snello, questo potrebbe effettivamente non riuscire mai; se tuttavia gli ordini vengono aggiunti costantemente da più vie, questo può essere un approccio inaccettabile.

+0

Grande risposta, oltre alla possibilità che ho citato nella mia interrogazione (utilizzando una procedura memorizzata per aggiornare un record utilizzando una connessione separata), la prima alternativa offre un'eccezionale scalabilità e throughput al costo di una certa complessità; la seconda alternativa è abbastanza semplice e potrebbe essere sufficiente quando il processo è semplificato (ad esempio utilizzando una coda di messaggi) o quando il tasso di creazione di nuovi ordini per ciascun tenant non è troppo alto. –

2

non so quanto sforzo sarebbe necessario per adattarsi al tuo scenario, ma hanno uno sguardo a questo come bene e vedere se è possibile modificarlo: SnowMaker – a unique id generator for Azure (or any other cloud hosting environment)

+1

Questa è una grande risorsa. Grazie per averlo portato alla mia attenzioneIl batching locale può essere abbastanza efficace e scalare bene, al costo di avere lacune nella sequenza e numeri fuori ordine cronologico, che è praticamente OK per gli ID interni ma solleva (infondate) preoccupazioni quando applicato ai numeri di controllo aziendale. –

+0

Consiglieresti comunque di utilizzare questo? –