SQLite 中的主键是不是需要索引?
Posted
技术标签:
【中文标题】SQLite 中的主键是不是需要索引?【英文标题】:Is an index needed for a primary key in SQLite?SQLite 中的主键是否需要索引? 【发布时间】:2021-01-08 11:47:37 【问题描述】:当一个整数列被标记为 SQLite 表中的主键时,是否也应该为它显式创建索引? SQLite 似乎不会自动为主键列创建索引,但考虑到它的目的,它可能还是会索引它? (我会一直在那个专栏上搜索)。
字符串主键的情况会有所不同吗?
【问题讨论】:
【参考方案1】:It does it for you.
INTEGER PRIMARY KEY 列除外,UNIQUE 和 PRIMARY KEY 约束是通过在数据库中创建索引来实现的(在 与“CREATE UNIQUE INDEX”语句相同的方式)。这样一个 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 或索引值进行的类似搜索的两倍。【参考方案2】:
如果一列被标记为 INTEGER PRIMARY KEY,它实际上是 通过指定任何其他 PRIMARY KEY 或索引值进行的类似搜索的两倍。这是因为:
...SQLite 表中的所有行都有一个 64 位有符号整数键,用于唯一标识其表中的行...搜索具有特定 rowid 的记录,或搜索具有指定范围内的 rowid 的所有记录是大约是通过指定任何其他 PRIMARY KEY 或索引值进行的类似搜索的两倍。
除了下面提到的一个例外,如果 rowid 表的主键由单个列组成,并且该列的声明类型为“INTEGER”(大小写任意混合), 然后该列将成为 rowid 的别名。
这样的列通常被称为“整数主键”。一种 PRIMARY KEY 列仅在声明的情况下才成为整数主键 类型名称正是“INTEGER”。其他整数类型名称,如“INT”或 “BIGINT”或“SHORT INTEGER”或“UNSIGNED INTEGER”导致主 键列表现为具有整数亲和性的普通表列 和唯一索引,而不是作为 rowid 的别名。
见:http://www.sqlite.org/lang_createtable.html#rowid
【讨论】:
【参考方案3】:数据库将始终默默地为唯一主键创建索引,以便在内部有效地检查它的唯一性。
创建后,它会在需要时使用它。
当然,它不会总是被集群化,如果你想要的话,你通常会在模式中指定它。
【讨论】:
【参考方案4】:使用时
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-tree 结构,对列a
的查询将很快:
数据 [...] 存储为 B-Tree 结构,其中每个表行包含一个条目,使用 rowid 值作为键。
注意:我没有引用的 [...] 部分是相对于普通表和带有 WITHOUT ROWID
子句的表之间差异的精度,但这完全超出了这里的主题。
【讨论】:
以上是关于SQLite 中的主键是不是需要索引?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以为使用 python 的 sqlite3 中的主键自动增量列选择第一个值?
使用 System.Data.Linq.Mapping 和自动递增 sqlite 数据库中的主键时出错