¿Cuál es la mejor estrategia de clave principal para una aplicación móvil de múltiples clientes en línea / fuera de línea con SQLite y la base de datos de Azure SQL como el almacén central?

¿Qué estrategia clave principal sería la mejor para usar en un modelo de base de datos relacional dado lo siguiente?

decenas de miles de usuariosMúltiples clientes por usuario (teléfono, tableta, escritorio)Millones de filas por mesa (en continuo crecimiento)

Azure SQL será el almacén de datos central que se expondrá a través de la API web. Los clientes incluirán una aplicación web y una serie de aplicaciones nativas, como iOS, Android, Mac, Windows 8, etc. La aplicación web requerirá una conexión "siempre activa" y no tendrá un almacén de datos local, sino que se recuperará y actualizará a través del api - piense CRUD vía RESTful API.

Todos los demás clientes (teléfono, tableta, escritorio) tendrán una base de datos local (SQLite). En el primer uso de este tipo de cliente, el usuario debe autenticarse y sincronizarse. Una vez autenticados y sincronizados, estos clientes pueden operar en modo fuera de línea (crear, eliminar y actualizar registros en la base de datos local de SQLite). Estos cambios eventualmente se sincronizarán con el backend de Azure.

La naturaleza distribuida de las bases de datos nos deja con un problema principal y la razón para hacer esta pregunta.

Esto es lo que hemos considerado hasta ahora:

GUID

Cada cliente crea sus propias claves. En la sincronización, hay una posibilidad muy pequeña de una clave duplicada, pero deberíamos tenerla en cuenta al escribir la funcionalidad en cada cliente para actualizar todas las relaciones con una nueva clave. Los GUID son grandes y cuando se consideran varias claves externas por tabla, el almacenamiento puede convertirse en un problema con el tiempo. Probablemente, el mayor problema es la naturaleza aleatoria de los GUID, lo que significa que no pueden (o no deben) usarse como el índice agrupado debido a la fragmentación. Esto significa que necesitaríamos crear un índice agrupado (tal vez arbitrario) para cada tabla.

Identidad

Cada cliente crea sus propias claves primarias. En la sincronización, estas claves se reemplazan con las claves generadas por el servidor. Esto agrega complejidad adicional al proceso de sincronización y obliga a cada cliente a "arreglar" sus claves, incluidas todas las claves externas en las tablas relacionadas.

Compuesto

A cada cliente se le asigna un ID de cliente en la primera sincronización. Esta identificación del cliente se usa junto con una identificación local de incremento automático como clave principal compuesta para cada tabla. Esta clave compuesta será única, por lo que no debería haber conflictos en la sincronización, pero sí significa que la mayoría de las tablas requerirán una clave primaria compuesta. El rendimiento y la complejidad de la consulta es la preocupación aquí

HiLo (compuesto fusionado)

Al igual que el enfoque compuesto, a cada cliente se le asigna un id de cliente (int32) en la primera sincronización. El id de cliente se fusiona con un id local único (int32) en una sola columna para hacer un id único de aplicación (int64). Esto no debería dar lugar a conflictos durante la sincronización. Si bien hay más orden en estas claves frente a los GUID, ya que los identificadores generados por cada cliente son secuenciales, habrá miles de identificadores únicos de clientes, ¿así que todavía corremos el riesgo de fragmentación en nuestro índice agrupado?

¿Estamos pasando por alto algo? ¿Hay otros enfoques que valga la pena investigar? Una discusión de los pros y los contras de cada enfoque sería muy útil.