小。速度很快。可靠。
选择任意三个。
聚集索引和WITH OUT ROWID优化

1引言

默认情况下,SQLite中的每一行都有一个特殊的列,通常称为"罗伊德“,它在表中唯一标识该行。但是如果将短语“WITH OUT ROWID”添加到创建表格声明,然后省略特殊的“rowid”列。有时省略rowid的空间和性能优势。

WITH OUT ROWID表是使用聚集索引作为主键。

1.1.语法

要创建WITH OUT ROWID表,只需添加关键字“WITH OT ROWID”到的末尾创建表格声明。例如:

如果不存在,则创建表格wordcount(文字主键,cnt整数)不带ROWID;

与所有SQL语法一样,关键字的大小写并不重要。可以写“没有rowid”或“没有rowid”或“WITHOUT rowid”,以及这将意味着同样的事情。

每个WITH OUT ROWID表必须具有主钥匙。出现错误如果带有with OUT ROWID子句的CREATE TABLE语句缺少PRIMARY KEY。

在大多数上下文中,普通表的特殊“rowid”列可以也称为“oid”或“rowid”。然而,只有“rowid”可以作为CREATE TABLE语句中的关键字。

1.2.兼容性

数据库版本3.8.2(2013-12-06)或更高版本必须使用WITH OUTROWID表。试图打开包含一个或多个但没有使用SQLite早期版本的ROWID表将导致“数据库架构格式错误”错误。

1.3.奇怪的事

WITH OUT ROWID仅在SQLite中找到,不兼容据我们所知,使用任何其他SQL数据库引擎。在一个优雅的系统中,所有表都将表现为WITH OUT ROWID表,即使没有WITH OUT ROWID关键字。然而,当SQLite最初设计时,它只使用整数划艇用于行键以简化实现。多年来,这种方法运行良好。但作为对SQLite增长了,对PRIMARY KEY真正起作用的表的需求增加了与底层行键相对应变得更加尖锐。不带ROWID的添加了概念为了在不倒退的情况下满足需求与数十亿已在使用的SQLite数据库兼容时间(约2013年)。

2与普通Rowid表的差异

WITH ROWID语法是一种优化。它没有提供新的能力。使用WITH OUT ROWID表可以完成的任何操作也可以用完全相同的方式,完全相同的语法,使用普通的rowid表。无ROWID的唯一优势表是它有时可以使用较少的磁盘空间和/或执行少量操作比普通的rowid表更快。

大多数情况下,普通的rowid表和WITHOUT rowid表是可互换的。但在以下方面还有一些附加限制不包含不适用于普通ROWID表的ROWID表:

  1. 每个WITH OUT ROWID表都必须有一个PRIMARY KEY。尝试创建WITHOUT ROWID表,但没有PRIMARY KEY结果出现错误。

  2. 相关的特殊行为”集成主键“不适用在WITH OUT ROWID表格上。在普通表中,“INTEGER PRIMARY KEY”表示该列是rowid的别名。但由于WITH OUT rowid中没有rowid表中的特殊含义不再适用。“整数主键”WITH OUT ROWID表中的列有效就像普通表中的“INT PRIMARY KEY”列:它是一个PRIMARYKEY有整数的密切关系.

  3. 自动更正不适用于WITH OUT ROWID表。这个自动更正机制假定存在rowid,因此它不适用于WITH OUT ROWID表。如果“AUTOINCREMENT”关键字在CREATE TABLE语句中用于a WITH OUT ROWID表格。

  4. 在WITH OUT中的PRIMARY KEY的每一列上强制使用NOT NULLROWID表。这符合SQL标准。PRIMARY KEY的每一列应单独为NOT NULL。然而,没有强制执行NOT NULL由于错误,早期版本的SQLite在PRIMARY KEY列上出现错误。当这个bug被发现时,已经有很多SQLite数据库由于担心破坏兼容性。因此,SQLite中的普通rowid表违反了SQL标准,并允许在PRIMARY KEY字段中使用NULL值。但没有ROWID表格确实遵循标准,如果试图在PRIMARY KEY列中插入NULL。

  5. 这个sqlite3_last_insert_rowid()功能不适用于WITH OUT ROWID表。插入WITH OUT ROWID不会更改sqlite3_last_insert_rowid()功能。这个last_insert_rowid()SQL语言函数也不受影响,因为它只是一个包装器sqlite3_last_insert_rowid().

  6. 这个增量blob I/O机制不起作用用于WITH OUT ROWID表格。增量BLOB I/O使用rowid创建方形3_球形对象执行直接I/O。但是,WITH OUT ROWID表没有ROWID,因此无法创建方形3_球形WITH OUT的对象ROWID表。

  7. 这个sqlite3_update_hook()接口不为更改触发回调到WITH OUT ROWID表。回调的一部分sqlite3_update_hook()是表的rowid已更改的行。但是,WITH ROWID表没有ROWID。因此,当一个没有ROWID的表发生变化时,更新挂钩不会被调用。

三。无ROWID表的优点

WITH OUT ROWID表是一种优化,可以减少存储和加工要求。

在普通SQLite表中,PRIMARY KEY实际上只是一个独特索引。用于查找磁盘上记录的键罗伊德.特别的“集成主键“普通SQLite表中的列类型使列成为rowid的别名,因此INTEGER PRIMARYKEY是真正的主键。但任何其他类型的主键,包括“INT PRIMARY KEY”只是普通rowid表中的唯一索引。

考虑一个表(如下所示),该表用于存储词汇量和出现次数一些文本语料库中的每个单词:

如果不存在,则创建表格wordcount(单词文本主键,cnt整数);

作为一个普通的SQLite表,“wordcount”实现为两个单独的B树。主表使用隐藏的rowid值作为键并将“word”和“cnt”列存储为数据。“文本主键”CREATE TABLE语句的短语导致创建唯一索引在“单词”栏上。此索引是使用“word”和“rowid”作为密钥并存储no的单独B-Tree数据。请注意,每个“单词”的完整文本存储两次:一次在主表中,一次在索引中。

考虑查询此表以查找单词“xsync”。:

选择cnt FROM wordcount WHERE word='xsync';

此查询首先必须搜索索引B-Tree以查找任何条目包含“word”的匹配值。当在中找到条目时提取索引,rowid并用于搜索主表。然后从主表中读取并返回“cnt”值。因此,两个需要单独的二进制搜索来满足请求。

WITH OUT ROWID表对等效项使用不同的数据设计表。

如果不存在,则创建表格wordcount(单词文本主键,cnt整数)不带ROWID;

在后一个表中,只有一个B-Tree使用“单词”列作为其键,“cnt”列作为其数据。(技术性:低级实现实际上将“word”和“cnt”存储在“key”中B树的区域。但除非您正在查看低级字节编码对于数据库文件,这一事实并不重要。)因为只有单个B-Tree,“word”列的文本只存储在数据库。此外,查询特定“单词”的“cnt”值由于“cnt”值可以直接从第一次搜索找到的记录中检索并且无需对rowid进行第二次二进制搜索。

因此,在某些情况下,WITHOUTROWID表可以使用大约一半的数量的磁盘空间,并且可以以几乎两倍的速度运行。当然,在实际模式,通常会有二级索引和/或独特的约束,情况更为复杂。但即便如此,在没有ROWID的情况下使用通常具有空间和性能优势在具有非整数或复合主键的表上。

4何时在没有ROWID的情况下使用

WITH OUT ROWID优化可能对表有帮助具有非整数或复合(多列)主键且不存储大字符串或BLOB。

没有ROWID表将正常工作(也就是说提供正确答案)。然而,在这种情况下,普通的rowid表将运行得更快。因此,这是一个很好的设计避免使用单列PRIMARY KEY创建with OUT ROWID表INTEGER类型。

当单个行不太大时,WITH OUT ROWID表工作得最好。一个很好的操作规则是WITH OUT ROWID表格的大小应小于数据库页面。这意味着行中包含的内容不应超过大约对于1KiB页面大小,每个字节为50字节;对于4KiB,每个字节约为200字节页面大小。WITH OUT ROWID表格将起作用(从这个意义上说他们得到了正确的答案),用于任意大的行-最大2GB-但传统的rowid表对于较大的行大小往往工作得更快。这是因为rowid表实现为B*-树木哪里所有内容都存储在树的叶子中,而没有ROWID表是使用普通的B树实现的,其内容存储在叶和中间节点。将内容存储在中间节点导致每个中间节点条目占用更多空间页面上的空间,从而减少扇出,增加搜索成本。

“sqlite3_analyzer.exe”实用程序,作为源代码提供在SQLite源代码树中,或作为SQLite下载页面,可以是用于测量现有SQLite中表行的平均大小数据库。

请注意,除了上面详述的几个拐角处的差异外,WITH OUT ROWID表和ROWID表的工作原理相同。它们都产生相同的答案给出了相同的SQL语句。所以这很简单在开发周期后期对应用程序运行实验,测试使用WITH OUT ROWID表是否有帮助。一个好的策略是在没有ROWID的情况下不必担心产品开发结束,然后返回并运行测试以查看如果将with OUT ROWID添加到具有非整数PRIMARY KEY的表中有帮助或影响性能,仅在这种情况下保留WITH OUT ROWID有帮助的地方。

5确定现有表是否没有ROWID

WITH ROWID表返回的内容与PRAGMA表格_信息PRAGMA表格_xinfo和普通人一样表。但与普通表不同,WITH OUT ROWID也响应PRAGMA索引_信息命令。这个PRAGMA索引_信息在WITH OUT ROWID表上返回有关PRIMARY KEY的信息用于表格。通过这种方式PRAGMA索引_信息命令可以是用于明确确定特定表是否为没有ROWID表或普通表-普通表将始终不返回任何行,但WITH OUT ROWID表将始终返回一行或多行。

此页面上次修改时间2023-10-10 17:29:48联合技术公司