ChatGPT解决这个技术问题 Extra ChatGPT

SQLite 中的主键是否需要索引?

当一个整数列被标记为 SQLite 表中的主键时,是否也应该为它显式创建索引? SQLite 似乎不会自动为主键列创建索引,但考虑到它的目的,它可能还是会索引它? (我会一直在那个专栏上搜索)。

字符串主键的情况会有所不同吗?


m
mafu

It does it for you.

除了 INTEGER PRIMARY KEY 列之外,UNIQUE 和 PRIMARY KEY 约束都是通过在数据库中创建索引来实现的(与“CREATE UNIQUE INDEX”语句的方式相同)。这种索引与数据库中的任何其他索引一样用于优化查询。因此,在已经共同受 UNIQUE 或 PRIMARY KEY 约束的一组列上创建索引通常没有优势(但开销很大)。


实际上,它说“PRIMARY KEY 属性通常会在指定为 PRIMARY KEY 的一个或多个列上创建一个唯一索引”。但是,该索引在 SQLite 管理应用程序中不可见,这就是我问的原因。
它在 sqlite_master 表中被提及,名称以 sqlite_autoindex_ 开头。
迟到了,但是@NicolasZozol 是的,如果父/引用字段不存在,您需要创建一个 UNIQUE 索引(或一个 UNIQUE 约束); 建议子/引用字段有一个索引(通常不是唯一的):see here
嗯,第 SQL Data Constraints here 节说:在大多数情况下,UNIQUE 和 PRIMARY KEY 约束是通过在数据库中创建唯一索引来实现的。 (例外情况是 WITHOUT ROWID 表上的 INTEGER PRIMARY KEY 和 PRIMARY KEY。)。所以答案并不总是正确的?
似乎 rowid 已编入索引但实现方式不同sqlite.org/lang_createtable.html#rowid rowid 表的数据存储为 B-Tree 结构,其中每个表行包含一个条目,使用 rowid 值作为键...搜索具有特定rowid ...大约是通过指定任何其他 PRIMARY KEY 或索引值进行的类似搜索的两倍。
C
Community

如果一列被标记为 INTEGER PRIMARY KEY,它实际上是通过指定任何其他 PRIMARY KEY 或索引值进行的类似搜索的两倍左右。这是因为:

... SQLite 表中的所有行都有一个 64 位有符号整数键,用于唯一标识其表中的行 ...搜索具有特定 rowid 的记录,或搜索具有指定范围内的 rowid 的所有记录大约是两倍与通过指定任何其他 PRIMARY KEY 或索引值进行的类似搜索一样快。除了下面提到的一个例外,如果 rowid 表的主键由单个列组成,并且该列的声明类型为“INTEGER”(大小写任意混合),则该列将成为 rowid 的别名。这样的列通常称为“整数主键”。如果声明的类型名称恰好是“INTEGER”,则 PRIMARY KEY 列仅成为整数主键。其他整数类型名称,如“INT”或“BIGINT”或“SHORT INTEGER”或“UNSIGNED INTEGER”会导致主键列表现为具有整数亲和性和唯一索引的普通表列,而不是 rowid 的别名。

请参阅:http://www.sqlite.org/lang_createtable.html#rowid


C
CashCow

数据库将始终默默地为唯一主键创建索引,因此它可以在内部有效地检查它的唯一性。

创建它后,它将在必要时使用它。

当然,它不会总是被集群化,如果你想要的话,你通常会在模式中指定它。


B
Basj

使用时

CREATE TABLE data(a INTEGER PRIMARY KEY, b, ...)

传统的附加(隐藏)列 rowid 将不存在:列 a 本身将是行 ID。

实际上,doc 指出:

在 SQLite 中,类型为 INTEGER PRIMARY KEY 的列是 ROWID 的别名(除了 WITHOUT ROWID 表),它始终是 64 位有符号整数。

also

如果 [...] 表的主键由单个列组成,并且该列的声明类型是“INTEGER”[...],则该列将成为 rowid 的别名。

由于 a 是行 ID,因此不需要索引,由于 B 树结构,对列 a 的查询将很快:

数据 [...] 存储为 B-Tree 结构,其中每个表行包含一个条目,使用 rowid 值作为键。

注意:我没有引用的 [...] 部分与普通表和带有 WITHOUT ROWID 子句的表之间的差异的精度有关,但这完全超出了这里的主题。