在SQLite中使用UUID作为主键的Android技术问题

35

我的应用程序需要与其他应用程序用户(在他们自己的设备上)同步。我还希望支持离线编辑,这些编辑会在用户连接到互联网时与其他协作用户同步。

因此,用户A会更改(在离线状态下)数据库中的某些数据(换句话说,更新数据库条目)或向数据库添加新记录。当用户A连接到互联网时,所有更改和新记录都会传递给其他协作用户。然后用户B将获取更改/更新并将其插入/更新到用户B的本地设备数据库中。

但是我需要确保整个系统中的数据库条目ID是唯一的。因此,我需要使用类似UUID的东西。

我的问题:在Android SQLite数据库表中,使用UUID(字符串/ Varchar)作为主键而不是自动递增的整数是否不好?

我猜使用字符串(UUID有36个字符)作为主键会有性能问题。

我猜索引uuid比索引整数需要更长时间(比较字符串与整数)。我也猜想,当我使用UUID时,每次插入新的数据库记录/条目时,数据库都需要重新索引主键列,因为主键索引不再按排序顺序排列(如果我使用自动递增的整数主键,那么每个未来记录都添加到末尾,因为新的自动递增主键始终是迄今为止最大的数字,因此索引将自动按排序顺序排列)。我还需要在2-3个表之间进行链接。我还猜想,在联接中比较字符串而不是整数会减慢数据库查询。

但是,我找不到其他实现这样的协作同步系统的可能性,所以我必须使用UUID,对吗?

另一种可能性是使用自动递增的整数主键,然后使用第二列uuid。因此,在用户本地设备上工作时,我将使用此主键(整数)进行JOIN等操作,而在与其他用户同步时,我将使用uuid列。

你们认为这种方法怎么样,或者你认为这太麻烦了,因为使用UUID作为主键不会带来明显的性能问题?
还有其他建议吗?

这是一篇旧帖子,但我想分享一个我已经实现的方法。 我为设备应用程序实例生成UUID并将其存储在共享首选项中。我在Room表中使用一个简单的自动生成的键(Int或Long)。在向服务器发送数据时,我在标头中包含应用程序实例UUID。在这个模型中,服务器可以区分和处理服务器表键的分配,这些键会同步回设备。 出于跨平台原因,我选择了UUID而不是FID。 显然,有很多方法来解决问题。 - 0x1b
2个回答

32
在 Android SQLite 数据库表中,使用 UUID (字符串 / varchar)作为主键而不是自增的整数可能会有问题。唯一肯定出现的问题是您将无法使用 CursorAdapter 及其子类来显示查询结果。CursorAdapter 需要在 Cursor 中具有唯一的整数 _id 列,而您可能没有这些列。因此需要创建自己的适配器,可以扩展 BaseAdapter 来进行处理。对于使用字符串(UUID 具有 36 个字符)作为主键是否会有性能问题,有可能,在设备大小的数据库上,这会转化为实际问题。对于如何实现协作同步系统,您需要某种类型的 UUID 用于网络协议,并且您需要将该 UUID 存储在数据库中。无法确定该 UUID 是否需要成为表的主键,因为不知道架构。另一个可能性是使用整数自动递增的主键,同时使用第二个 uuid 列。然后使用本地整数 ID 对用户本地设备进行操作,使用 UUID 列与其他用户同步。您需要一个 UUID->本地整数 ID 映射表,使用 UUID 在您的网络协议中,并大多保持本地数据库使用本地整数 ID。无法确定此方法是否会显着提高性能(特别是考虑到增加的数据库模式复杂性)。

在我看来,要么进行一些性能测试,以便获得一些具体可比较的数据,要么只有在数据库I/O看起来缓慢时才需要担心。


1
你可以将UUID存储为16字节的二进制。 - Eir Nym
@EirNym:知道这些很好,但我不明白它与问题、答案或你对我的回答的否定有什么关系。 - CommonsWare
你可以告诉别人,在SQLite3中,UUID只有一种ASCII表示法,并且解释了这种表示法的缺点。而二进制表示法则没有这些缺点:它足够快,适用于Android 2.3+设备,这也是2013年推荐的最低要求。如今我们拥有更快的设备,我们不仅可以使用SQLite3作为数据库引擎,但它仍然是常见的选择。 - Eir Nym
@EirNym:“你说SQLite3中UUID的ASCII表示只有一个,并讲述了其缺点”-我没有看到我的回答中有任何符合您描述的内容。例如,“ASCII”一词仅出现在您的评论和此回复评论中。该答案侧重于“CursorAdapter”的要求问题,而您的解决方案也没有解决这个问题。 - CommonsWare
这是类似于BLOB的类型,您必须使用文本表示进行直接值比较,但它足够快以用作主键/外键。是的,您可以开枪并使用varchar主键,但是您可以解释说二进制表示法可以使用更少的缺点。Android的代码不会改变。 - Eir Nym
@EirNym:“但是你可以解释一下二进制表示法的使用会有较少的缺点”--欢迎发表您的意见。我不同意。“Android的代码不会改变”--是的,至少在尝试使用CursorAdapter时会改变。 - CommonsWare

6

在与UUID / SQLite相关的问题中,可以找到一组UUID作为二进制和文本的性能结果:https://dev59.com/HGgu5IYBdhLWcg3wbGel#11337522

根据结果,在索引时,二进制和字符串UUID都可以在SQLite中高效创建和查询。另一个权衡是是否更喜欢可读性强的字符串,还是更小的二进制文件大小。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接