sqlite性能优化之路-配置优化

作者: 酱君挺怎样 | 来源:发表于2018-05-12 17:27 被阅读1次

    测试环境

    cpu型号 内存 操作系统
    Intel(R) Xeon(R) CPU E5-2687W 3.00GHz 8GB windows 7

    初始数据

    不做任何优化的场景下,sqlite性能达到 100 ~ 120 qps左右。这样的一个数值,在客户端场景下,已经足以满足大部分需求。

    但对于服务端的sdk,根据业务场景也许用来记录服务端的行为日志等操作。由于服务端处数据量处理能力远远大于客户端,因此 100 ~ 120 的qps就显得相形见绌。因此有了下面的优化思路。

    Synchronous设置

    synchronous 获取或设置当前磁盘的同步模式,该模式用于控制SQLite写入磁盘的时机。

    Pragma值 描述
    0或OFF 不进行同步。写入数据后传递给操作系统则完成操作,类似mmap的操作,剩下的交给操作系统完成。
    1或NORMAL sqlite2的默认模式,在关键磁盘操作的每个序列后同步。不像FULL模式那么频繁刷盘,有小几率在电源故障或磁盘不可用时导致数据库损坏。
    2或FULL sqlite3的默认模式,在每个关键磁盘操作后同步,性能差。数据库在紧急时刻暂停以确定数据写入磁盘,使得系统崩溃或电源出问题时,确保数据库重启不会损坏。

    通过上述可以看到,sqlite3默认采用最安全也是最慢的方式来刷盘写入数据库。如果我们业务中对
    数据丢失的情况不是太敏感,而更关注于性能,我们可以设置为OFF。

    当设置为OFF后,写入性能可提高3倍。大约提升到 300 的 qps

    journal_mode设置

    journal_mode 获取或设置控制日志文件如何存储和处理的日志模式。

    Pragma 值 描述
    DELETE 默认模式。事务结束时,日志文件删除
    TRUNCATE 日志文件被阶段为零字节长度
    PERSIST 日志文件保留在原地,但头部被重写,表明日志不再有效
    MEMORY 日志记录在内存中,而不是磁盘
    OFF 不保留任务日志
    WAL write ahead log

    journal,为的是数据库事务的rollback操作。
    数据库begin trans写入时,首先写入journal文件中,commit操作时,根据journal-mode来处理journal日志文件。
    若在commit之前由于断电等原因造成无法commit,当再次启动时,通过journal文档做回滚操作,保证数据库的完整性和一致性。

    WAL机制:修改不直接写入数据库文件中,而是直接一个WAL的文件中,若事务失败,WAL记录被忽略;若事务成功,随后在某个checkpoint时间点写回数据库。

    • 优点
      • 读写可完全并发执行,不会互相阻塞(但写之间不能并发) - 测试过程读写不能并发执行
      • WAL多数情况下都有更好性能(因为无需写入两个文件 - journal和数据文件)
      • 磁盘IO行为更容易被预测
    • 缺点
      • 每个数据库现在对应3个文件:*.db, -wal,-shm
      • 当写入数据达到GB级别,数据库性能下降
      • 必须要sqlite 3.7.0版本以上版本才支持

    为了避免读取的数据不一致,查询时也需要读取WAL文件,并记录一个结尾标记(end mark)。这样的代价就是读取会变得稍慢,但是写入会变快很多。要提高查询性能的话,可以减小WAL文件的大小,但写入性能也会降低。 需要注意的是,低版本的SQLite不能读取高版本的SQLite生成的WAL文件,但是数据库文件是通用的。这种情况在用户进行iOS降级时可能会出现,可以把模式改成delete,再改回WAL来修复。

    关于WAL性能,曾经有人测试与写内存性能差距不大。

    当journal_mode设置为WAL后,写入性能可提高4倍,大约提升到400 的 qps




    若同时设置两个参数,写入性能提升至10000以上的qps

    可关注我的微信公众号:酱君挺怎样


    微信公众号.jpg

    相关文章

      网友评论

        本文标题:sqlite性能优化之路-配置优化

        本文链接:https://www.haomeiwen.com/subject/wqjhdftx.html