使用SQLite和Azure SQL数据库作为中央存储的在线/离线多客户端移动应用程序的最佳主键策略是什么?

use*_*640 13 sqlite android database-design azure ios

在给定以下内容的情况下,哪种主键策略最适合用于关系数据库模型?

  • 成千上万的用户
  • 每个用户多个客户端(手机,平板电脑,桌面)
  • 每桌数百万行(不断增长)

Azure SQL将成为将通过Web API公开的中央数据存储.客户端将包括一个Web应用程序和许多本机应用程序,包括iOS,Android,Mac,Windows 8等.Web应用程序将需要"始终开启"连接,并且不会有本地数据存储,而是将检索和更新通过api - 通过RESTful API思考CRUD.

所有其他客户端(手机,平板电脑,桌面)都将拥有本地数据库(SQLite).首次使用此类客户端时,用户必须进行身份验证和同步.经过身份验证和同步后,这些客户端可以在脱机模式下运行(在本地SQLite数据库中创建,删除和更新记录).这些更改最终将与Azure后端同步.

数据库的分布式特性给我们留下了一个主要的关键问题以及提出这个问题的原因.

以下是我们迄今为止所考虑的内容:

GUID

每个客户端都创建自己的密钥.在同步时,重复密钥的可能性非常小,但我们需要通过将功能写入每个客户端以使用新密钥更新所有关系来解释它.GUID很大,当考虑每个表的多个外键时,存储可能会成为一个问题.可能最大的问题是GUID的随机性,这意味着由于碎片,它们不能(或不应该)用作聚簇索引.这意味着我们需要为每个表创建一个聚簇索引(可能是任意的).

身分

每个客户端都创建自己的主键.在同步时,这些密钥将替换为服务器生成的密钥.这增加了同步过程的额外复杂性,并迫使每个客户端"修复"其密钥,包括相关表上的所有外键.

综合

在首次同步时为每个客户端分配一个客户端ID.此客户端ID与本地自动递增ID一起用作每个表的复合主键.此复合键将是唯一的,因此同步时不应存在冲突,但它确实意味着大多数表将需要复合主键.性能和查询复杂性是这里的关注点.

HiLo(合并复合材料)

与复合方法一样,每个客户端在第一次同步时都会被分配一个客户端ID(int32)客户端ID与唯一的本地ID(int32)合并为一个列,以创建应用程序范围的唯一ID(int64).这应该导致同步期间没有冲突.虽然这些密钥与GUID的顺序更多,因为每个客户端生成的ID是顺序的,但是会有数千个独特的客户端ID,因此我们是否仍然存在聚集索引碎片的风险?

我们忽略了什么吗?还有其他值得研究的方法吗?讨论每种方法的优缺点将非常有帮助.

Mar*_*kle 1

要记住的关键(双关语)是为存储在持久存储中的每个对象拥有一个唯一的密钥。如何处理该对象的存储完全取决于您以及您访问该密钥的方法。您列出的每个策略都有其自己的原因,但最终它们会在数据库中存储某个对象的密钥,因此可以更改其所有属性,同时在数据库中保留相同的对象引用。