SQLite As An Application File Format
SQLite As An Application File Format
Executive Summary
具有定义模式的SQLite数据库文件通常会提供出色的应用程序文件格式。这里有十几个理由:
- 简化的应用开发
- 单文件文件
- 高级查询语言
- 无障碍内容
- 跨平台
- 原子交易
- 增量和连续更新
- 易于扩展
- 性能
- 多进程并发使用
- 多种编程语言
- 更好的应用
在首先更仔细地考虑“应用程序文件格式”的含义之后,将在下面更详细地描述这些点中的每一个。另请参阅此白皮书的简短版本。
What Is An Application File Format?
“应用程序文件格式”是用于将应用程序状态持久化到磁盘或在程序之间交换信息的文件格式。目前有数千种应用程序文件格式正在使用。这里只是一些例子:
- DOC - Word Perfect和Microsoft Office文档
- DWG - AutoCAD图纸
- PDF - Adobe公司的可移植文档格式
- XLS - Microsoft Excel电子表格
- GIT - Git源代码库
- EPUB - 非Kindle电子书使用的电子出版格式
- ODT - OpenOffice和其他人使用的Open Document格式
- PPT - Microsoft PowerPoint演示文稿
- ODP - OpenOffice和其他人使用的Open Document演示文稿格式
我们区分“文件格式”和“应用程序格式”。文件格式用于存储单个对象。因此,例如,GIF或JPEG文件存储单个图像,而XHTML文件存储文本,因此这些文件是“文件格式”而不是“应用程序格式”。相反,EPUB文件存储文本和图像(包含XHTML和GIF / JPEG文件),所以它被认为是“应用程序格式”。这篇文章是关于“应用程序格式”。
文件格式和应用程序格式之间的界限是模糊的。本文称JPEG为文件格式,但对于图像编辑器,JPEG可能被认为是应用程序格式。这很大程度上取决于上下文。对于本文,让我们说一个文件格式存储单个对象,应用程序格式存储许多不同的对象及其相互之间的关系。
大多数应用程序格式都符合以下三个类别之一:
完全自定义格式。
自定义格式是专门为单个应用程序设计的。DOC,DWG,PDF,XLS和PPT是自定义格式的示例。自定义格式通常包含在单个文件中,以便于传输。它们通常也是二进制的,尽管DWG格式是一个明显的例外。自定义文件格式需要专门的应用程序代码才能读取和写入,并且通常无法从常用工具(如unix命令行程序和文本编辑器)访问。换句话说,自定义格式通常是“不透明的斑点”。要访问自定义应用程序文件格式的内容,需要专门设计用于读取和/或写入该格式的工具。
堆文件格式。
有时应用程序状态被存储为文件的层次结构。Git就是一个很好的例子,尽管这种现象经常发生在一次性和定制的应用程序中。一堆文件格式基本上使用文件系统作为键/值数据库,将小块信息存储到单独的文件中。这提供了使内容更易于访问诸如文本编辑器或“awk”或“grep”等常用实用程序的优点。但即使堆文件格式中的许多文件易于阅读,通常也有一些文件具有自己的自定义格式(例如:Git“Packfiles”),因此是“不透明的斑点”,不可读或不可读无需专门工具即可写入。把一堆文件从一个地方或一台机器搬到另一个地方或机器上也不太方便,比移动单个文件要多。例如,很难在电子邮件附件中生成一堆文件。最后,一堆文件格式打破了“文档隐喻”:没有一个用户可以指向的文件就是“文档”。
包裹的文件夹格式。
一些应用程序使用一堆文件,然后将其封装到某种单文件容器中,通常是一个ZIP压缩文件。EPUB,ODT和ODP就是这种方法的例子。一本EPUB书籍实际上只是一个ZIP存档,其中包含用于书籍章节文本的各种XHTML文件,用于该艺术品的GIF和JPEG图像,以及一个专门的目录文件,告诉电子书阅读器如何将所有XML和图像文件放在一起。OpenOffice文档(ODT和ODP)也是ZIP档案,其中包含表示其内容的XML和图像以及显示组成部分之间相互关系的“目录”文件。
一个包裹的一堆文件格式是一个完整的自定义文件格式和纯文件堆栈格式之间的折中。由于组件部分仍然可以使用任何常用ZIP归档程序访问,所以包装的一堆文件格式不是一个不透明的blob,因为该组件部分仍然可以使用任何常用ZIP归档程序访问,但格式不像纯粹的一堆-files格式,因为仍然需要ZIP存档器,而且通常不使用命令行工具(如文件层次结构中的“find”),而无需先解压缩它。另一方面,一个包裹的文件堆栈格式通过将所有内容放入单个磁盘文件来保留文档隐喻。而且由于它是压缩的,所以包裹的一堆文件格式往往更加紧凑。
与自定义文件格式一样,与纯粹的文件堆栈格式不同,一个包裹的一堆文件格式不容易编辑,因为通常必须重写整个文件以更改任何组件部分。
本文档的目的是争论第四类新的应用程序文件格式:一个SQLite数据库文件。
SQLite As The Application File Format
任何可以记录在一堆文件中的应用程序状态也可以通过一个简单的键/值模式记录在SQLite数据库中,如下所示:
CREATE TABLE files(filename TEXT PRIMARY KEY, content BLOB
如果内容被压缩,那么这样一个SQLite数据库与等效ZIP压缩文件大小相同(±1%),并且它的优点是能够在不重写整个文档的情况下更新单个“文件”。
但是SQLite数据库并不局限于一堆简单的键/值结构,比如一堆文件数据库。一个SQLite数据库可以有数十或数百或数千个不同的表,每个表有数十或数百或数千个字段,每个字段都有不同的数据类型和约束以及特定的含义,所有这些都相互交叉引用,适当且自动地索引以便快速检索,并全部高效且紧凑地存储在单个磁盘文件中。所有这些结构都是通过SQL模式为人类简洁地记录下来的。
换句话说,一个SQLite数据库可以完成一堆文件或者一堆文件格式可以做的所有事情,再加上更多,并且更加清晰。SQLite数据库是比键/值文件系统或ZIP归档更通用的容器。(有关详细示例,请参阅OpenOffice案例研究文章。)
理论上,SQLite数据库的强大功能可以使用自定义文件格式来实现。但是任何与关系数据库一样具有表现力的自定义文件格式可能需要巨大的设计规范和数十或数十万行代码才能实现。最终的结果将是一个“不透明的斑点”,如果没有专门的工具就无法进入。
因此,与其他方法相比,使用SQLite数据库作为应用程序文件格式具有显着的优势。列举并阐述了以下几个优点:
简化的应用开发。
读取或写入应用程序文件不需要新的代码。一个只需要链接到SQLite库,或者将单个“sqlite3.c”源文件与其余的应用程序C代码一起包含,SQLite将负责所有的应用程序文件I / O。这可以将应用程序代码大小减少数千行,相应地节省了开发和维护成本。SQLite是世界上使用最多的软件库之一。实际上,每天在智能手机和小工具以及桌面应用程序中使用数百亿SQLite数据库文件。SQLite经过仔细测试并证明可靠。它不是一个需要大量调优或调试的组件,允许开发人员专注于应用程序逻辑。
单文件文件。
SQLite数据库包含在单个文件中,该文件很容易复制,移动或附加。“文件”隐喻被保留下来。
SQLite没有任何文件命名要求,因此应用程序可以使用任何自定义文件后缀来帮助将文件标识为“属于”应用程序。SQLite数据库文件的头文件中包含一个4字节的应用程序ID,可以将其设置为应用程序定义的值,然后用于标识实用程序(如文件(1))的文档“类型” ,进一步增强文档隐喻。
高级查询语言。
SQLite是一个完整的关系数据库引擎,这意味着应用程序可以使用高级查询访问内容。应用程序开发人员不需要花时间思考如何从文档中检索他们所需的信息。开发人员编写表达他们想要的“什么”信息的SQL,让数据库引擎找出如何最好地检索该内容。这有助于开发人员“正面向上”运作,并继续专注于解决用户的问题,并避免花费时间“低头”摆弄低级文件格式细节。一堆文件格式可以被视为一个键/值数据库。键/值数据库根本比没有数据库好。但没有交易或索引或高级查询语言或适当的模式,
无障碍内容。
保存在SQLite数据库文件中的信息可以使用常用的开源命令行工具 - 默认情况下安装在Mac和Linux系统上的工具访问,并且可以在Windows上作为自包含的EXE文件免费使用。与自定义文件格式不同,应用程序特定的程序不需要读取或写入SQLite数据库中的内容。SQLite数据库文件不是不透明的blob。确实,命令行工具(如文本编辑器或“grep”或“awk”)在SQLite数据库上没有用处,但SQL查询语言是检查内容的更强大和更方便的方式,因此无法使用“grep”和“awk”等并不被视为损失。
SQLite数据库是一个定义明确且记录良好的文件格式,它被数百万个应用程序广泛使用,并且在2004年开始向后兼容,并且在接下来的几十年内将保持持续兼容。SQLite数据库文件的寿命对于定制的应用程序尤其重要,因为它允许在将来丢失文档内容的很长时间后访问文档内容。数据寿命比代码长。
跨平台的。
SQLite数据库文件可以在32位和64位计算机之间以及大端和小端体系结构之间以及任何类型的Windows和类Unix操作系统之间移植。使用SQLite应用程序文件格式的应用程序可以存储二进制数字数据,而不必担心整数或浮点数的字节顺序。文本内容可以读写为UTF-8,UTF-16LE或UTF-16BE,SQLite将自动执行任何必要的翻译。
原子交易。
写入SQLite数据库是原子的。它们要么完全发生,要么根本不发生,即使在系统崩溃或电力故障期间也是如此。所以,没有任何文件被破坏的危险,仅仅是因为在写入到磁盘上的同一时刻电源发生了故障。
SQLite是事务性的,这意味着可以将多个更改组合在一起,以使其全部或全部不发生,并且如果在提交之前发现问题则可以回滚更改。这允许应用程序逐步进行更改,然后在将更改提交到磁盘之前对结果数据运行各种完整性和一致性检查。该化石 DVCS 使用这种技术来验证没有仓库的历史前已经向每一个变化丢失。
增量和连续更新。
在写入SQLite数据库文件时,只有实际更改的那部分文件才写入磁盘。这使得写作更快速并且可以节省SSD的磨损。与自定义和包装文件堆栈格式相比,这是一个巨大的优势,它们通常需要重写整个文档才能更改单个字节。纯堆文件格式也可以在一定程度上进行增量更新,尽管通过堆栈文件格式(单个文件)的写入粒度通常比使用SQLite(单个页面)更大。SQLite也支持持续更新。除了在内存中收集更改,然后仅在文件/保存操作中将它们写入磁盘,更改可以在发生时写回到磁盘。这避免了在系统崩溃或电力故障时丢失工作。一个自动撤消/重做堆栈,
易于扩展。
随着应用程序的增长,只需向模式添加新表格或向现有表格添加新列,即可将新功能添加到SQLite应用程序文件格式中。添加列或表并不会改变先前查询的含义,因此,为了确保遗留列和表的含义得到保留,需要小心谨慎地维护向后兼容性。
当然,也可以扩展定制或堆积文件格式,但这样做通常要困难得多。如果添加了索引,则必须定位和修改更改相应表的所有应用程序代码,以使这些索引保持最新。如果添加了列,那么访问相应表的所有应用程序代码都必须进行定位和修改,以考虑新列。
性能。
在许多情况下,SQLite应用程序文件格式将比堆叠文件格式或自定义格式更快。除了原始读取和写入速度更快外,SQLite通常可以显着缩短启动时间,因为不必将整个文档读取并分析到内存中,应用程序可以执行查询以仅提取初始屏幕所需的信息。随着应用程序的不断发展,它只需要加载绘制下一个屏幕所需的材料,并且可以丢弃之前不再使用的屏幕中的信息。这有助于控制应用程序的内存占用。一堆文件格式可以像SQLite一样逐步读取。但是很多开发人员都惊讶地发现,SQLite可以从其数据库中读取和写入更小的BLOB(大小小于约100KB),这些BLOB可以更快地读取或写入文件系统中的单独文件。(有关详细信息,请参阅文件系统和内部与外部BLOB的比35%更快)。与操作关系数据库引擎相关的开销,但不应假定直接文件I / O比SQLite数据库I / O更快,因为通常情况并非如此。无论哪种情况,如果SQLite应用程序中出现性能问题,那么这些问题通常可以通过向模式添加一个或两个CREATE INDEX语句或者可能一次运行ANALYZE来解决,而不必触摸单行应用程序代码。但是,如果性能问题出现在自定义或堆叠文件格式中,
多进程并发使用。
SQLite自动协调对来自多个线程和/或进程的同一文档的并发访问。两个或多个应用程序可以同时连接和读取同一文档。写入是序列化的,但由于写入通常只需要几毫秒,应用程序只需轮流写入。SQLite自动确保文档的低级格式不被破坏。相比之下,使用自定义文件格式或堆积文件格式来实现这一点,则需要在应用程序中提供广泛的支持。而支持并发所需的应用程序逻辑是臭名昭着的bug磁铁。
多种编程语言。
虽然SQLite本身是用ANSI-C编写的,但是你可以想到的几乎所有其他编程语言都存在接口:C ++,C#,Objective-C,Java,Tcl,Perl,Python,Ruby,Erlang,JavaScript等等。所以程序员可以用任何他们最喜欢的语言进行开发,并且最适合项目的需求。
SQLite应用程序文件格式是单独程序的集合或“联合”情况下的最佳选择,通常用不同的语言和不同的开发团队编写。这通常出现在研究或实验室环境中,其中一个团队负责数据采集,而其他团队负责不同阶段的分析。每个团队都可以使用他们最喜欢的任何硬件,操作系统,编程语言和开发方法,只要所有程序使用具有通用模式的SQLite数据库,它们都可以互操作。
更好的应用。
如果应用程序文件格式是SQLite数据库,则该文件格式的完整文档由数据库模式组成,可能还有一些关于每个表格和列代表的内容。另一方面,自定义文件格式的描述通常运行数百页。一堆文件格式虽然比完全自定义格式更简单,更容易描述,但仍然比SQL模式转储更大更复杂,因为仍然需要描述单个文件的名称和格式。
这不是一个小问题。清晰,简明,易于理解的文件格式是任何应用程序设计的关键部分。弗雷德布鲁克斯,在他的畅销的计算机科学文本,The Mythical Man-Month
记载:
表示是计算机编程的本质。
...
展示你的流程图并隐藏你的表格,我会继续迷惑。给我看你的表格,我通常不需要你的流程图; 他们会很明显。
Rob Pike在他的规则规则中
表达了同样的想法:
数据占主导地位。如果你选择了正确的数据结构并且组织得很好,算法几乎总是不言而喻的。数据结构,而不是算法,是编程的核心。
2006年6月27日,Linus Torvalds在Git邮件列表上用了不同的词语:
糟糕的程序员担心代码。好的程序员担心数据结构及其关系。
重点在于:SQL数据库模式几乎总是能够更好地定义和组织表和数据结构及其关系。清晰,简洁和明确的表示几乎总是会导致应用程序执行得更好,问题更少,开发和维护也更容易。
Conclusion
对于每种情况,SQLite都不是完美的应用程序文件格式。但是在很多情况下,SQLite比自定义文件格式,一堆文件或者一堆文件都要好得多。SQLite是一种高级,稳定,可靠,跨平台,广泛部署,可扩展,高性能,可访问的并发文件格式。它值得您考虑作为下一个应用程序设计的标准文件格式。
SQLite is in the Public Domain.