Was ist die beste Primärschlüsselstrategie für eine mobile Online- / Offline-Multiclient-Anwendung mit SQLite- und Azure SQL-Datenbank als zentralem Speicher?

Welche Primärschlüsselstrategie eignet sich am besten für ein relationales Datenbankmodell, wenn Folgendes gegeben ist?

Zehntausende von BenutzernMehrere Clients pro Benutzer (Telefon, Tablet, Desktop)Millionen Zeilen pro Tabelle (stetig wachsend)

Azure SQL wird der zentrale Datenspeicher sein, der über die Web-API verfügbar gemacht wird. Die Clients umfassen eine Webanwendung und eine Reihe nativer Apps, einschließlich iOS, Android, Mac, Windows 8 usw. Die Webanwendung erfordert eine „Always-On“ -Verbindung und verfügt nicht über einen lokalen Datenspeicher, sondern ruft stattdessen ab und aktualisiert sie über die API - think CRUD über die RESTful API.

Alle anderen Clients (Telefon, Tablet, Desktop) haben eine lokale Datenbank (SQLite). Bei der ersten Verwendung dieses Client-Typs muss sich der Benutzer authentifizieren und synchronisieren. Nach der Authentifizierung und Synchronisierung können diese Clients im Offlinemodus arbeiten (Erstellen, Löschen und Aktualisieren von Datensätzen in der lokalen SQLite-Datenbank). Diese Änderungen werden schließlich mit dem Azure-Backend synchronisiert.

Die Verteilung der Datenbanken führt zu einem Problem mit dem Primärschlüssel und dem Grund für die Beantwortung dieser Frage.

Folgendes haben wir bisher in Betracht gezogen:

GUID

Jeder Client erstellt seine eigenen Schlüssel. Bei der Synchronisierung ist die Wahrscheinlichkeit sehr gering, dass ein Schlüssel doppelt vorhanden ist. Sie müssen dies jedoch berücksichtigen, indem Sie Funktionen in jeden Client schreiben, um alle Beziehungen mit einem neuen Schlüssel zu aktualisieren. GUIDs sind groß, und wenn mehrere Fremdschlüssel pro Tabelle berücksichtigt werden, kann die Speicherung mit der Zeit zu einem Problem werden. Das wahrscheinlich größte Problem ist die Zufälligkeit von GUIDs, was bedeutet, dass sie aufgrund von Fragmentierung nicht als Clustered-Index verwendet werden können (oder sollten). Dies bedeutet, dass wir für jede Tabelle einen (möglicherweise willkürlichen) Clustered-Index erstellen müssen.

Identität

Jeder Client erstellt seine eigenen Primärschlüssel. Bei der Synchronisierung werden diese Schlüssel durch vom Server generierte Schlüssel ersetzt. Dies erhöht die Komplexität des Synchronisierungsprozesses und zwingt jeden Client, seine Schlüssel einschließlich aller Fremdschlüssel in verwandten Tabellen zu "reparieren".

Composite

Jedem Client wird bei der ersten Synchronisierung eine Client-ID zugewiesen. Diese Client-ID wird in Verbindung mit einer lokalen, automatisch inkrementierenden ID als zusammengesetzter Primärschlüssel für jede Tabelle verwendet. Dieser zusammengesetzte Schlüssel ist eindeutig, sodass bei der Synchronisierung keine Konflikte auftreten sollten. Dies bedeutet jedoch, dass für die meisten Tabellen ein zusammengesetzter Primärschlüssel erforderlich ist. Leistung und Abfragekomplexität sind hier das Problem.

HiLo (Merged Composite)

Wie beim zusammengesetzten Ansatz wird jedem Client bei der ersten Synchronisierung eine Client-ID (int32) zugewiesen. Die Client-ID wird mit einer eindeutigen lokalen ID (int32) in einer einzelnen Spalte zusammengeführt, um eine anwendungsweite eindeutige ID (int64) zu erhalten. Dies sollte zu keinen Konflikten während der Synchronisierung führen. Diese Schlüssel sind zwar geordneter als GUIDs, da die von jedem Client generierten IDs sequenziell sind. Es gibt jedoch Tausende eindeutiger Client-IDs. Gehen wir also weiterhin das Risiko einer Fragmentierung in unserem Clustered-Index ein?

Übersehen wir etwas? Gibt es andere Ansätze, die es wert sind, untersucht zu werden? Eine Diskussion der Vor- und Nachteile jedes Ansatzes wäre sehr hilfreich.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage