在 SQLite 表中使用文本作为主键不好?

Posted

技术标签:

【中文标题】在 SQLite 表中使用文本作为主键不好?【英文标题】:Using text as a primary key in SQLite table bad? 【发布时间】:2014-04-18 15:40:24 【问题描述】:

在 SQLite 数据库中将文本作为主键是不是很糟糕?我听说由于性能原因这很糟糕,这是真的吗?在这种情况下,rowid 会被用作实际的主键吗?

【问题讨论】:

【参考方案1】:

在 SQLite 数据库中将文本作为主键是不是很糟糕?听说性能不好,这是真的吗?

从正确性的角度来看,TEXT PRIMARY KEY 是可以的。

从性能的角度来看,更喜欢INTEGER 键。但与任何性能问题一样,请自行衡量,看看您的数据和用例是否存在显着差异。

在这种情况下,rowid 会被用作实际的主键吗?

只有INTEGER PRIMARY KEYROWID 有别名。其他类型的主键没有,除非指定WITHOUT ROWID,否则会有隐式整数rowid。 Reference.

【讨论】:

那么隐含的rowid是干什么用的? 为了清楚起见,您能否明确说明是否是 TEXT 主键引用的隐式 rowid?【参考方案2】:

在现实世界中,如果我们谈论 UUID,使用字符串作为主键有很多好处。能够在创建实体“护照”时准确地创建它可以大大简化异步代码和/或分布式系统(如果我们谈论的是更复杂的移动客户端/服务器架构)。

在性能方面,我在运行基准以执行 10000 次主键查找时没有发现任何可衡量的差异,因为实际上,数据库索引在运行索引搜索时既不存储也不比较字符串。

【讨论】:

我会说 UUID 由有限数量的符号 (VARCHAR) 组成。所以它有点多字节整数,你可以把它看成是对 char, word, int, long,.... 【参考方案3】:

是的,如果你使用 TEXT,你会得到 android.database.sqlite.SQLiteConstraintException:唯一约束失败:TableName.ColumnName(代码1555)

如果此插入成功,SQLite 具有要插入的会话并返回最后插入的行的行 ID。 否则将返回 -1。

return 被映射到 _ID ,这就是他们强制你为表接口 BaseColumns 的原因

很奇怪,插入调用必须返回 rowid,而不是布尔值左右

我希望 SQLite 中有 TEXT PRIMARY KEY 功能

【讨论】:

【参考方案4】:

PRIMARY KEY 类型的字段意味着比较值。比较数字比比较文本更简单。

原因是64位数值比较有专门的汇编指令。这总是比比较理论上可以无限大小的文本快得多。

比较数字的例子:

CMP DX, 00  ; Compare the DX value with zero
JE  L7      ; If yes, then jump to label L7
.
.
L7: ...

在此处阅读有关CMP 汇编指令的更多信息:https://www.tutorialspoint.com/assembly_programming/assembly_conditions.htm

知道这一点让我们知道数字总是更具表现力(至少在我们今天拥有的计算中)。

【讨论】:

【参考方案5】:

在 SQLite 数据库中将文本作为主键是不是很糟糕?我听说 出于性能原因,这很糟糕,这是真的吗?

我从未听说有人在表中使用字符串作为主键。对我来说(老实说,我也希望对其他人)非常“丑陋”的做法,性能非常低。

如果您将使用字符串作为主键,您需要考虑“一些”事情:

3 个符号的组合就够了吗? 还是应该使用 5 个符号?

在这里,每一行必须有相同的格式(当然是可读性问题)并且必须是唯一的。哦!下面是 "piggy work" -> 你需要创建一些 "unique string generator" 来生成唯一的1 字符串标识符2.

还有下一个问题值得考虑:

更长的字符串= 自动比较难比较 桌子的大小急剧增加,因为很明显 字符串的大小比数字大得多 行数 - 如果你使用字符串作为主键是很疯狂的 表可以有 1000+ 行

这是一个更复杂的主题,但我想说好的,对于非常小的表,可以使用字符串作为主键(如果它有意义的话),但如果你要看看缺点,它是更好的技术一定要用数字作为主键!

什么是结论?

我不建议你使用字符串作为主键。它有更多的缺点作为优点(它真的有一些优点吗?)。

使用数字作为主键要好得多(我不敢说最好)。

在这种情况下,rowid 会被用作实际的主键吗?

如果您将使用字符串作为主要不。

1真正的字符串很少是唯一的。

2当然,你可以说你可以从行中的项目名称创建标识符,但这又是意大利面条代码(项目可以具有相同的名称)。

【讨论】:

我的字符串来自服务器,保证是唯一的,并且总是设置长度改变这个答案的事实吗? @mpellegr 一般来说,使用字符串作为主键不是我在回答中写的好习惯;) 我即将创建一个表,该表有一个唯一的、索引的文本列,并且对该表的每个查询都将使用它来引用行。该表不打算用外键引用。当我想到这个问题时,我几乎只是从例程中添加了一个整数 ID 列,我为什么要这样做?那么,在这种特殊情况下,是否有任何理由创建 ID 列? 您是否能够测量与文本主键相关的“非常低的性能”?因为this question 的答案(除了SQLite 部分与当前的非常相似)没有提到这样的问题。 所有好的和有效的点,但有一个边缘情况,递增整数只会导致问题,即当您需要在多个设备和主数据存储之间保持数据同步时.而且 GUID 足够独特。

以上是关于在 SQLite 表中使用文本作为主键不好?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 SQLite 表中检索最后一个自动增量 ID?

使用 char(17) 作为主键在 SQL Server 的表中存储 VIN 号如何影响性能? [关闭]

我们可以在 Sqlite 数据库中使用 Guid 作为主键吗

跟踪 SQL 中的新主键

[QT][SQL]sql学习记录3_sqlite 使用

Android:在 SQLite 中使用 UUID 作为主键