幽默:如何在静态文件托管服务器上使用数据库?


如何在静态文件托管服务器上使用数据库?首先,将SQLite(用C编写)编译为WebAssembly。SQLite可以使用emscripten进行编译,而无需进行任何修改,并且sql.js库是wasm代码周围的薄JS包装器。
sql.js只允许您创建和读取完全位于内存中的数据库-因此,我实现了一个虚拟文件系统,当SQLite尝试从文件系统读取时,该虚拟文件系统使用HTTP Range请求获取数据库的块:sql.js-httpvfs。从SQLite的角度来看,它看起来像是生活在具有空文件系统的普通计算机上,但可以读取/wdi.sqlite3文件的空文件系统。当然它不能写入该文件,但是只读数据库仍然非常有用。
由于通过HTTP获取数据的开销非常大,因此我们需要分块获取数据,并在请求数量和使用的带宽之间找到平衡。幸运的是,SQLite已经使用用户定义的页面大小(默认为4 KiB)将其数据库组织在“ pages ”中。我已将此数据库的页面大小设置为1 KiB。
这是一个简单的索引查找查询的示例:

select indicator_code, long_definition from wdi_series where indicator_name
    = 'Literacy rate, youth total (% of people ages 15-24)'

运行上面的查询,然后查看页面读取日志。SQLite对该查询进行7页读取。

  • 仅读取三页即可获得一些架构信息(这些信息已被缓存)
  • 两页读取是索引中的索引查找 on wdi_series (indicator_name)
  • wdi_series表数据上有两次页面读取(第一次通过主键查找行值,第二次从溢出页面获取文本数据)

索引以及表读取都是B树查找。
 
好处:DOM作为数据库
由于我们已经在浏览器中运行数据库,为什么不使用浏览器称为dom虚拟表作为数据库?
select count(*) as number_of_demos from dom
  where selector match '.content div.sqlite-httpvfs-demo';
select count(*) as sqlite_mentions from dom
  where selector match '.content p' and textContent like '%SQLite%';

我们甚至可以将元素直接插入DOM中:

insert into dom (parent, tagName, textContent)
    select 'ulouttable1', 'li', short_name
    from wdi_country where currency_unit = 'Euro'

更新DOM中的元素:

update dom set textContent =
  get_flag("2-alpha_code") || ' ' || textContent
from wdi_country
where selector match 'ulouttable1 > li'
  and textContent = wdi_country.short_name

当然,这里的一切都是开源的。sqlite包装器的主要实现是在sql.js-httpvfs中。该博客文章的源代码是pandoc markdown文件,而演示是自定义的“围栏fenced代码块” React组件
点击标题