微信团队开源的终端数据库WCDB有什么优势?

1、前言

今天看到微信团队的一篇文章,说是自家的开源的终端数据库WCDB进行了重大升级
原文章在这里,感兴趣的朋友们可以围观一下:《五年沉淀,微信全平台终端数据库WCDB迎来重大升级》

wcdb数据库的新版本提供了更丰富的开发语言支持,更强大的SQL表达能力,更安全的数据存储能力,更灵活的数据扩展能力,更细致的性能优化能力等。今天我们来看看到底是怎么个事儿

WCDB是微信团队开源的一款基于SQLite的终端数据库。它的特点包括:

  1. 支持多种开发语言:WCDB支持C++、Java、Kotlin、Swift和ObjC这五种主要的终端开发语言,覆盖了Android、iOS、Windows、macOS和Linux这五大终端平台。

  2. 集成查询:WCDB提供了Winq(WCDB Integrated Query),使得开发者可以使用原生语法编写任意SQL,告别字符串拼接的胶水代码。

  3. 数据库备份与修复:WCDB推出了全新的数据备份和修复方案,大幅提升了数据修复率,同时将数据备份的性能消耗降至可忽略不计。

  4. 数据迁移和数据压缩:WCDB提供了数据迁移和数据压缩这两个新功能,让开发者仅通过简单的配置,就能高效处理复杂业务中的数据过度聚集和数据过度膨胀这两大难题。

  5. FTS5优化:WCDB对SQLite的FTS5组件进行了优化,重新设计了FTS5分词器,并丰富了分词器的能力,还支持了拼音搜索。

  6. 可中断事务:WCDB支持可中断事务,让一系列DB操作尽量保持在一个事务中执行,同时能够及时响应主线程的阻塞事件,避免了主线程的卡顿问题。

  7. 数据安全性:WCDB采用了全新的数据备份方案、修复方案等,保障数据的安全性。

  8. 性能优化:WCDB在数据库读写、数据迁移、数据压缩等方面进行了性能优化,提高了数据库操作的效率。

2、内容概况

思维导图

在这里插入图片描述

代码框架

在这里插入图片描述

开源地址

https://github.com/Tencent/wcdb

3、功能说明

  1. 更丰富的开发语言支持

    • 说明:新版WCDB通过使用C++作为核心逻辑的实现语言,使得其他开发语言如Java和Kotlin可以通过桥接方法接入这个核心逻辑。这样的设计允许不同语言版本的WCDB共享同一套核心功能,同时保持语言特有的接口层。
    • 举例:假设一个跨平台的应用程序需要在iOS(使用Objective-C或Swift)和Android(使用Java或Kotlin)上运行。开发者可以为每个平台编写相应的数据库访问代码,而这些代码在底层都调用同一个C++实现的数据库逻辑,从而确保了代码的一致性和可维护性。
  2. 更强大的SQL表达能力

    • 说明:新版WCDB对Winq进行了重写,使其能够更好地支持复杂SQL语句的编写。Winq将SQL语句中的Token抽象成C++类,并通过链式调用的方式,让开发者能够以一种接近自然语言的方式编写SQL语句,提高了开发效率和代码的可读性。
    • 举例:考虑一个场景,开发者需要查询一个订单表中所有金额大于某个值的订单。使用Winq,开发者可以这样编写查询语句:database.query("SELECT * FROM orders WHERE amount > ?", [minAmount]); 这样的代码不仅易于理解,而且减少了出错的可能性。
  3. 更安全的数据存储能力

    • 说明:新版WCDB引入了全新的数据备份和修复方案,通过备份数据库的关键信息,如表名和页号映射,以及数据的CRC校验值,来提高数据的安全性。即使在数据库文件损坏的情况下,也能够通过这些备份信息恢复数据,极大地提高了数据的修复率。
    • 举例:在一个即时通讯应用中,聊天记录对于用户来说非常重要。如果因为设备故障导致数据库损坏,新版WCDB可以通过备份方案快速恢复聊天记录,保证用户数据不丢失。
  4. 更灵活的数据扩展能力

    • 说明:新版WCDB提供了数据迁移和数据压缩功能,使得开发者能够更灵活地处理数据。数据迁移功能允许开发者在不中断服务的情况下,将数据从一个表迁移到另一个表。数据压缩功能则可以减少数据库占用的存储空间,提高读写性能。
    • 举例:假设一个社交应用需要存储大量的用户动态信息,这些信息通常包含大量的XML或JSON格式的数据。通过WCDB的数据压缩功能,可以显著减少这些数据占用的空间,同时提高数据读写的速度,从而提升应用的整体性能。
  5. 更细致的性能优化能力

    • 说明:新版WCDB通过优化FTS5(全文搜索)组件和引入可中断事务等特性,进一步提升了数据库的性能。FTS5优化使得全文搜索更加高效,而可中断事务则允许在长时间运行的数据库操作中,主线程可以及时响应用户操作,避免应用卡顿。
    • 举例:在一个电商平台中,用户搜索商品时需要快速返回搜索结果。通过WCDB对FTS5的优化,可以确保搜索操作快速且准确,提供更好的用户体验。同时,当后台需要处理大量数据更新时,可中断事务保证了应用的响应性,即使用户在数据更新过程中进行其他操作,应用也能保持流畅。

使用示例

// C++
database.insertObjects<Sample>(Sample(1, "text"), myTable);
database.updateRow("text2", WCDB_FIELD(Sample::content), myTable, WCDB_FIELD(Sample::id) == 1);
auto objects = database.getAllObjects<Sample>(myTable, WCDB_FIELD(Sample::id) > 0);
database.deleteObjects(myTable, WCDB_FIELD(Sample::id) == 1);
// Java
database.insertObject(new Sample(1, "text"), DBSample.allFields(), myTable);
database.updateValue("text2", DBSample.content, myTable, DBSample.id.eq(1));
List<Sample> objects = database.getAllObjects(DBSample.allFields(), myTable, DBSample.id.gt(0));
database.deleteObjects(myTable, DBSample.id.eq(1));
// Kotlin
database.insertObject<Sample>(Sample(1, "text"), DBSample.allFields(), myTable)
database.updateValue("text2", DBSample.content, myTable, DBSample.id.eq(1))
val objects = database.getAllObjects<Sample>(DBSample.allFields(), myTable, DBSample.id.gt(0))
database.deleteObjects(myTable, DBSample.id.eq(1))
// Swift
try database.insert(Sample(id:1, content:"text"), intoTable: myTable)
try database.update(table: myTable,
                    on: Sample.Properties.content,
                    with: "text2"
                    where:Sample.Properties.id == 1)
let objects: [Sample] = try database.getObjects(fromTable: myTable,
                                                where: Sample.Properties.id > 0)
try database.delete(fromTable: myTable where: Sample.Properties.id == 1)
// Objc
[database insertObject:sample intoTable:myTable];
[database updateTable:myTable
          setProperty:Sample.content
              toValue:@"text2"
                where:Sample.id == 1];
NSArray* objects = [database getObjectsOfClass:Sample.class
                                     fromTable:myTable
                                         where:Sample.id > 0];
[database deleteFromTable:myTable where:Sample.id == 1];

重点答疑

WCDB在处理数据迁移时采用了什么策略

  1. 首先,WCDB会对迁移的表进行配置,包括新表和旧表的字段、约束、索引等信息。新表的字段可以是旧表字段的子集,但不要求两者都有相同的约束和索引。新旧表可以有或者没有rowid,也可以有不同的主键。

  2. WCDB支持将未加密的数据库迁移到加密的数据库,或者将已加密的数据库重加密。还可以通过配置迁移的表来筛选需要迁移的部分数据,实现将一张表的数据拆分到多张表的效果,或者清理冗余数据。

  3. 在数据迁移过程中,WCDB会在子线程中每隔2秒花10毫秒执行一次数据迁移,直到数据迁移完整。如果需要加快迁移速度,WCDB也提供了手动执行迁移的接口。

  4. 为了减少数据迁移对业务逻辑的影响,WCDB采用了兼容旧表和新表的方案。在迁移过程中,业务逻辑可以继续使用旧表进行开发,而WCDB会自动处理新旧表之间的兼容问题。

  5. WCDB还提供了一种无感知的数据迁移方案,即在执行数据库操作请求时,会先对其使用的数据库句柄进行迁移配置,然后检测旧表是否存在。如果旧表不存在,说明迁移已经完成,直接执行SQL。如果旧表存在,则创建一个temp view,用于后续的兼容。WCDB会预处理数据库的操作请求,修改SQL,再进行真正的执行。这个预处理过程可以确保业务逻辑在迁移过程中不受影响。

新版WCDB在数据迁移和压缩方面的扩展能力有哪些具体表现

  1. 数据迁移能力:
  • 支持跨数据库迁移,将一个数据库中的表迁移到另一个数据库中。
  • 支持增量备份,将数据库中的数据备份到一个增量备份文件中,以便在需要时恢复数据。
  • 提供了一个无感知的数据库迁移方案,使得开发者可以在业务逻辑读写数据库时全部只读打开主数据库文件,只有在 checkpoint 时才可写打开主数据库文件,从而最大限度地减少主数据库文件的可写句柄的存活时间,防止外部逻辑误写。
  1. 数据压缩能力:
  • 支持多种压缩方式,包括 Zstd 的默认压缩方式、单字典压缩方式和多字典压缩方式,多字典压缩可以根据表中某个字段的值来采用不同的压缩字典。
  • 支持压缩多字段,一个正在压缩的表随时可以再添加新的压缩字段,满足扩展性的需求。
  • 支持数据压缩和数据迁移同时独立进行,开发者可以给一个正在迁移的表同时配置上数据压缩,这样数据在迁移时会压缩之后再写入新表,压缩和迁移可以各自独立开始,独立结束,互不干扰。

如何在WCDB中实现数据备份和修复方案

在WCDB 1.0中,备份和修复方案主要是针对SQLite数据库的页码进行备份,以解决数据库损坏后数据丢失的问题。然而,这种方案对于磁盘损坏导致的大面积数据丢失情况修复效果并不理想。

在新版WCDB中,备份和修复方案得到了重大升级。除了备份master表,还增加了备份普通表的表名到其叶子页页号和crc校验值的映射。这样一来,修复的时候可以根据页号直接找到普通表的数据,校验crc值未变,即可确认数据没有损坏或变更,从而将未损坏的数据完整恢复到新数据库。此外,还优化了备份性能,使得平均备份耗时仅为63ms,即便是大到10G的DB,备份耗时也不到0.9秒。
在这里插入图片描述
在这里插入图片描述

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小鱼儿小小林

赞赏是鼓励,点赞是美意

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值