在 GitHub 页面上托管 SQLite 数据库

2021-07-31 15:55:21

我正在写一个小网站来显示 Youtube 创作者随着时间的推移有多少赞助内容的统计数据,当时我注意到我经常编写一个小工具作为网站,从数据库中查询一些数据,然后将其显示在图表、表格中,或类似。但是如果你想使用一个数据库,你要么需要编写一个后端(然后你需要永远托管和维护)或者将整个数据集下载到浏览器中(当数据集超过 10MB 时,这不是那么好)。过去,当我在某个时候为这些小型项目使用后端服务器时,某些外部 API 出现故障或密钥过期,或者我忘记了后端并停止为使用的任何 VPS 付费。然后当我几年后重新审视它时,我很生气它已经消失并诅咒自己依赖外部服务 - 或者我自己照顾了更长的时间。托管静态网站比“真实”服务器容易得多——有许多免费且可靠的选项(如 GitHub、GitLab Pages、Netlify 等),而且它可以毫不费力地扩展到基本上无限。所以我写了一个工具,可以在静态托管的网站中使用真正的 SQL 数据库!这是一个使用 World Development Indicators 数据集的演示 - 一个包含 6 个表和超过 800 万行(总共 670 MiByte)的数据集。如您所见,我们可以查询 wdi_country 表,同时只获取 1kB 的数据!这是一个完整的 SQLite 查询引擎。因此,我们可以使用例如 SQLite JSON 函数:

我们还可以注册 JS 函数,以便在查询中调用它们。这是一个使用 getFlag 函数获取国家/地区国旗表情符号的示例: 那么您如何在静态文件主机上使用数据库?首先,SQLite(用 C 编写)被编译成 WebAssembly。 SQLite 可以用 emscripten 编译而无需任何修改,而 sql.js 库是一个围绕 wasm 代码的瘦 JS 包装器。 sql.js 只允许你创建和读取完全在内存中的数据库 - 所以我实现了一个虚拟文件系统,当 SQLite 尝试从文件系统读取时,它使用 HTTP 范围请求获取数据库块: sql.js-httpvfs .从 SQLite 的角度来看,它看起来就像是在一台普通的计算机上,除了一个可以读取的名为 /wdi.sqlite3 的文件之外,它的文件系统是空的。当然不能写入这个文件,但是只读数据库还是很有用的。由于通过 HTTP 获取数据有相当大的开销,我们需要以块的形式获取数据,并在请求数量和使用的带宽之间找到一些平衡。幸运的是,SQLite 已经使用用户定义的页面大小(默认为 4 KiB)在“页面”中组织其数据库。我已将此数据库的页面大小设置为 1 KiB。运行上面的查询并查看页面读取日志。 SQLite 为该查询执行 7 页读取。三页读取只是为了获取一些模式信息(这些已经缓存了) 两次页读取是在 wdi_series 表数据上(第一个通过主键查找行值,第二个从溢出页面获取文本数据)

一个更复杂的问题:根据 2010 年之后的最新数据,哪些国家的青年识字率最低?上面的查询应该执行 10-20 个 GET 请求,总共获取 130 - 270KiB,具体取决于您是否也运行了上述演示。请注意,它只需要执行 20 个请求,而不是 270 个(正如一次以 1 KiB 获取 270 KiB 时所预期的那样)。那是因为我实现了一个预取系统,该系统试图通过三个独立的虚拟读取头来检测访问模式,并以指数方式增加顺序读取的请求大小。这意味着索引扫描或表扫描读取超过几 KiB 的数据只会导致在扫描的总字节长度中为对数的请求数量。您可以通过查看上面页面读取日志中的“访问模式”列来查看此效果。只有当我们在数据库中有与查询匹配良好的索引时,所有这些才有效。例如,上面查询中使用的索引是 INDEX ON wdi_data (indicator_code, country_code, year, value)。如果该索引不包括值列,SQLite 引擎将不得不执行另一个随机访问(不可预测)读取,因此 HTTP 请求来检索每个数据点的实际值。如果索引按 country_code、indicator_code、... 排序,那么我们将能够快速获取单个国家/地区的所有指标,但不是单个指标的所有国家/地区值。我们还可以利用 SQLite FTS 模块,以便我们可以对数据库中文本较多的信息进行全文搜索——在这种情况下,数据库中有 1000 多个人类发展指标,并且有更长的描述。 indicator_search FTS 表中的数据总量约为 8 MB。上面的查询应该只获取大约 70 KiB。你可以在这里看到它是如何构建的。最后,这里更完整地展示了该系统的实用性 - 这是一个交互式图表,显示了几个国家随时间的发展,对于您想要使用数据集中的任何指标的任何国家: 国家:指标:互联网用户是个人在过去 3 个月内使用过互联网(从任何地方)。可以通过电脑、手机、个人数字助理、游戏机、数字电视等使用互联网。

Internet 是一个世界范围的公共计算机网络。它提供对包括万维网在内的多种通信服务的访问,并传送电子邮件、新闻、娱乐和数据文件,而与使用的设备无关(不假定仅通过计算机 - 也可以通过移动电话、PDA、游戏机、数字电视等)。访问可以通过固定或移动网络。有关来源和国家/地区说明的其他/最新信息,另请参阅:https://www.itu.int/en/ITU-D/Statistics/Pages/stat/default.aspx 数字和信息革命改变了方式世界学习、交流、做生意和治疗疾病。新的信息和通信技术 (ICT) 为所有国家各行各业的进步提供了巨大的机会——经济增长、改善健康、更好的服务提供、通过远程教育学习以及社会和文化进步的机会。今天的智能手机和平板电脑已经计算机能力相当于昨天的计算机,并提供类似的功能范围。因此,设备融合使传统定义变得过时。需要有关 ICT 的接入、使用、质量和可负担性的可比统计数据,以便为该行业制定促进增长的政策,并监测和评估该行业对发展的影响。尽管许多国家都可以获得基本接入数据,但在大多数发展中国家,人们对谁在使用 ICT 知之甚少;它们的用途(学校、工作、商业、研究、政府);以及它们如何影响人和企业。衡量 ICT 促进发展的全球伙伴关系正在帮助发展中国家制定标准、统一信息和通信技术统计并建设统计能力。然而,尽管发展中世界取得了显着进步,但 ICT 富人和穷人之间的差距仍然存在。请注意,许多指标仅适用于某些国家/地区,例如“妇女认为丈夫在烧饭时殴打妻子是合理的”指标仅基于在欠发达国家进行的调查。既然我们已经在我们的浏览器中运行了一个数据库,为什么不将我们的浏览器用作使用名为 dom 的虚拟表的数据库呢?