在SQLite数据库中,使用文本作为主键是否会影响性能?听说这样做会降低性能,这是真的吗?如果这样做,rowid是否会被用作实际的主键?
在SQLite数据库中,使用文本作为主键是否会影响性能?听说这样做会降低性能,这是真的吗?如果这样做,rowid是否会被用作实际的主键?
在SQLite数据库中,将文本作为主键是否不好?我听说这会影响性能,这是真的吗?
从正确性的角度来看,TEXT PRIMARY KEY
是可以的。
从性能的角度来看,最好使用 INTEGER
键。但是对于任何性能问题,都需要根据自己的数据和使用情况进行测量,以查看是否存在显着差异。
那么在这种情况下,ROWID
会被用作实际的主键吗?
只有 INTEGER PRIMARY KEY
与 ROWID
别名相同。其他类型的主键不会,除非指定了 WITHOUT ROWID
。参考资料。
在现实世界中,如果我们使用UUID作为主键,那么使用字符串作为主键有很多好处。能够在实体"护照"创建的时刻恰好创建实体可以大大简化异步代码和/或分布式系统(如果我们谈论更复杂的移动客户端/服务器架构)。
至于性能方面,在运行10000个主键查找的基准测试时,我没有发现任何可衡量的差异,因为在运行索引搜索时,数据库索引既不存储也不比较字符串。
(2)Richard Hipp(drh)于2021-03-04 16:00:22回复1 [source]
这两种方法都应该可以正常工作。将哈希值存储为BLOB可能会非常稍微快一些,因为(如您所观察到的)内容较少,因此文件I/O较少。
类似于此的是Fossil版本控制系统。但它将哈希值存储为文本而不是blob。性能不是问题,而且文本在开发人员调试时更容易处理。
使用文本主键在本质上没有问题。主键的有效性在于它是可排序的,并且在表中具有唯一值;除此之外,数据类型并不严格要求。然而,当数据是文本时,通常来自“现实世界”的数据源会排除将其用作主键的实用性。使用任意的、无意义的整数作为主键意味着您不必担心这样的问题。
这可能是整数主键最好的地方,甚至可以说比整数与字符串比较的速度更快。与整数比较相比,字符串比较通常对计算机而言需要更多的工作,确实如此,但在这种情况下这可能并不重要。SQLite在任何表中都为主键创建索引,这意味着即使您有百万条记录,SQLite在最坏的情况下只需要执行大约13次比较就能找到行(O(log n))。除非遇到极端情况,否则这不太可能对性能产生重大影响,我想。
顺便提一下,如果你打算使用文本作为主键,你可能要考虑使用SQLite的WITHOUT ROWID
功能。一个带有文本主键的表不太可能需要rowid列,因为rowid本质上是一个整数主键。WITHOUT ROWID
不仅可以消除rowid列,还告诉SQLite将表本身的搜索树基于你指定的主键而不是rowid。否则,它会创建两个搜索树,一个用于表本身的主搜索树使用rowid键,另一个用于将文本主键与rowid关联的独立搜索树。这浪费空间并增加了使用文本主键进行查找时不必要的开销,假设你不需要rowid。
SQLite的WITHOUT ROWID
文档解释了所有这些内容。他们给出了一个在文本语料库中存储单词计数的表的示例,其中单词作为主键,这对我来说是一个很好的文本主键适用的情况的例子。
是的,如果您使用TEXT,则会出现以下错误: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: TableName.ColumnName (code 1555)
如果插入成功,SQLite会话将插入并返回最后一行插入的行ID。否则将返回-1。
返回映射到_ID,这就是它们强制您为表接口BaseColumns的原因。
很奇怪插入调用必须返回rowid,而不是布尔值或其他内容
我希望SQLite中有TEXT 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。
了解这一点让我们知道数字在计算机性能方面总是更为出色的(至少在目前的计算中)。
这是一个更复杂的主题,但我想说,对于非常小的表,如果有意义的话,可能可以使用字符串作为主键,但是如果您看一下缺点,使用数字作为主键肯定是更好的技术!
那结论呢?
我不建议您使用字符串作为主键。 它的缺点比优点多(它真的有一些优点吗?)。
使用数字作为主键是更好的选择(我害怕说是最佳实践)。
在这种情况下,rowid会被用作实际的主键吗?
如果您将字符串用作主键,则不会。
1实际上,字符串很少是唯一的。
2当然,你可以说你可以从行中的项目名称创建标识符,但这又是一种意大利面式代码(项目可能具有相同的名称)。
WITHOUT ROWID
,SQlite将使用行ID作为表的主搜索树的键,并创建一个单独的搜索树来将文本主键与其行ID关联起来(因为任何主键列都会获得唯一索引)。因此,对于具有文本主键的表来说,通常使用WITHOUT ROWID
是个好主意。我认为整数与字符串比较速度在几乎任何SQLite表中并不重要,因为主键列上有索引。(有关更多详细信息,请参阅下面我的回答。) - Zoë Sparks