Qual é a melhor estratégia de chave primária para um aplicativo móvel multicliente on-line / off-line com o SQLite e o banco de dados SQL do Azure como o repositório central?

Qual estratégia de chave primária seria melhor usar para um modelo de banco de dados relacional dado o seguinte?

dezenas de milhares de usuáriosvários clientes por usuário (telefone, tablet, desktop)milhões de linhas por tabela (crescendo continuamente)

O Azure SQL será o repositório de dados central que será exposto via API da Web. Os clientes incluirão um aplicativo da Web e vários aplicativos nativos, incluindo iOS, Android, Mac, Windows 8, etc. O aplicativo da Web exigirá uma conexão "sempre ativa" e não terá um armazenamento de dados local, mas recuperará e atualizará através da API - pense em CRUD via API RESTful.

Todos os outros clientes (telefone, tablet, desktop) terão um db local (SQLite). Na primeira utilização deste tipo de cliente, o usuário deve autenticar e sincronizar. Depois de autenticados e sincronizados, esses clientes podem operar em um modo offline (criando, excluindo e atualizando registros no banco de dados SQLite local). Essas alterações acabarão sendo sincronizadas com o backend do Azure.

A natureza distribuída dos bancos de dados nos deixa com um problema fundamental e a razão para fazer essa pergunta.

Aqui está o que consideramos até agora:

GUID

Cada cliente cria suas próprias chaves. Em sincronia, há uma chance muito pequena de uma chave duplicada, mas precisamos explicá-la escrevendo a funcionalidade em cada cliente para atualizar todos os relacionamentos com uma nova chave. Os GUIDs são grandes e quando várias chaves estrangeiras por tabela são consideradas, o armazenamento pode se tornar um problema ao longo do tempo. Provavelmente, o maior problema é a natureza aleatória dos GUIDs, o que significa que eles não podem (ou não devem) ser usados ​​como o índice clusterizado devido à fragmentação. Isso significa que precisaríamos criar um índice clusterizado (talvez arbitrário) para cada tabela.

Identidade

Cada cliente cria suas próprias chaves primárias. Na sincronização, essas chaves são substituídas por chaves geradas pelo servidor. Isso adiciona complexidade adicional ao processo de sincronização e força cada cliente a “consertar” suas chaves, incluindo todas as chaves estrangeiras em tabelas relacionadas.

Composto

Cada cliente recebe um ID de cliente na primeira sincronização. Esse ID de cliente é usado em conjunto com um ID de incremento automático local como uma chave primária composta para cada tabela. Essa chave composta será única, portanto, não haverá conflitos na sincronização, mas significa que a maioria das tabelas exigirá uma chave primária composta. A complexidade de desempenho e consulta é a preocupação aqui.

HiLo (composto mesclado)

Como a abordagem composta, cada cliente recebe um ID de cliente (int32) na primeira sincronização. O ID do cliente é mesclado com um ID local exclusivo (int32) em uma única coluna para criar um ID exclusivo (int64) amplo do aplicativo. Isso deve resultar em nenhum conflito durante a sincronização. Embora haja mais ordem para essas chaves vs GUIDs, já que os IDs gerados por cada cliente são sequenciais, haverá milhares de IDs de clientes exclusivos, então ainda corremos o risco de fragmentação em nosso índice clusterizado?

Estamos negligenciando alguma coisa? Existem outras abordagens que valem a pena investigar? Uma discussão dos prós e contras de cada abordagem seria bastante útil.

questionAnswers(1)

yourAnswerToTheQuestion