美文网首页数据库&数据存储
Sqlite 数据库的性能

Sqlite 数据库的性能

作者: 介和 | 来源:发表于2018-11-12 19:14 被阅读0次

    一、可优化的切入点

    1 使用事务  (已用)

            本质:减少数据库的 open 和 close,减少文件的反复打开读写关闭

            事务的实现是依赖 sqlite 运行时产生的临时文件,借助这个临时文件来完成原子操作和回滚功能。既然属于文件,就符合Unix的文件范型(Open-Read/Write- Close),因而对于批量的修改操作会出现反复打开文件读写再关闭的操作。 

    2 使用索引 (未用)

            索引,使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。

            在表中建立索引,然后在索引中找到符合查询条件的索引值,快速找到表中对应的记录。

    Create Index ’index_name’ On ’table_name’;

            对于增加,更新和删除来说,使用了索引会变慢;

            建立索引会增加数据库的大小,为数据量比较小的表建立索引,往往会事倍功半。

            所以,使用索引需要考虑实际情况进行利弊权衡,对于查询操作量级较大,业务对要求查询要求较高的,还是推荐使用索引的。

    3 使用预编译SQL语句(已用)

           Sqlite执行需要将程序中的sql语句编译成对应的SQLiteStatement 

            比如:select * from ,被执行100次就需要编译100次。

            对于批量处理插入或者更新的操作,我们可以使用显示编译来做到重用SQLiteStatement。

    4 使用异步操作(已用)

            数据库的操作,属于本地IO,通常比较耗时,如果处理不好,很容易导致卡顿,因此建议将这些耗时操作放入异步线程中处理。

    5  内存模式 (未用)

       以空间换时间 

    (1)内存数据库:

              在SQLite中,数据库通常是存储在磁盘文件中的。然而在有些情况下,我们可以让数据库始终驻留在内存中。最常用的一种方式是在调用sqlite3_open()的时候,数据库文件名参数传递":memory:",如:

        rc = sqlite3_open(":memory:", &db) ;

            在调用完以上函数后,不会有任何磁盘文件被生成,取而代之的是,一个新的数据库在纯内存中被成功创建了。由于没有持久化,该数据库在当前数据库连接被关闭后就会立刻消失。需要注意的是,尽管多个数据库连接都可以通过上面的方法创建内存数据库,然而它们却是不同的数据库,相互之间没有任何关系。事实上,我们也可以通过Attach命令将内存数据库像其他普通数据库一样,附加到当前的连接中,如:

        ATTACH DATABASE ':memory:' AS aux1 ;

    (2)临时数据库:

            在调用sqlite3_open()函数或执行ATTACH命令时,如果数据库文件参数传的是空字符串,那么一个新的临时文件将被创建作为临时数据库的底层文件,如:

        rc = sqlite3_open("", &db);

        或

        ATTACH  DATABASE  '' AS aux2; 

            和内存数据库非常相似,两个数据库连接创建的临时数据库也是各自独立的,在连接关闭后,临时数据库将自动消失,其底层文件也将被自动删除。

            尽管磁盘文件被创建用于存储临时数据库中的数据信息,但是实际上临时数据库也会和内存数据库一样通常驻留在内存中,唯一不同的是,当临时数据库中数据量过大时,SQLite为了保证有更多的内存可用于其它操作,因此会将临时数据库中的部分数据写到磁盘文件中,而内存数据库则始终会将数据存放在内存中。

    6  WAL 与 DEL (已用)

         (1)默认的是DEL ,读写操作时,DEL模式要处理各种锁。 写操作是独享的,写阻塞读。读完成的时候才能写,读阻塞写。

          数据由1万增加到2万。读100条的时候写10条,写10条数据所耗时间 。

    WAL模式所耗时间为DEL模式所耗时间的1/4。

            数据由1万增加到2万。读100条的时候写10条。读100条数据所耗时间。

          DEL模式所耗时间略高于WAL模式所耗时间。时间越长次数越多,WAL效率越高。

      (2) WAL模式下要更进一步提升性能的话,可以考虑改变 checkpoint。

          当然WAL模式也有一些缺点:

    · 当每个事务数据量比较大时,接近或超过1000页的数据量时,会导致WAL内容频繁同步至实际数据库文件,导致性能下降。

           我们在把  checkpoint 改成了10000(默认是1000),checkpoint = 1000 是日志文件 1M 的时候回写到数据库,改成 10000 就变成了 日志文件 10M 时回写数据到数据库。有2倍+的提升。

    7  分库与分表(偏业务层面)(已用)

            (1)  随着表中数据量的减少,查询的相同数量数据的时间逐渐减少。

        例如有与100个人的聊天记录,分表后,每打开一个会话时,读数据时,对应的表的规模是分表前的 1/100。查询速度必然增加。写数据时也是如此。

      (2)在设计数据库时,我们会把一个对象的属性分成不同的列按行存储。如果属性是个数量不定的数组,切忌不要把这个数组属性放到一个新表里面。上面我们提到过数据操作最耗时的其实是访问外存上面的数据。当数据量很大时,多张表的外存访问是非常慢的。这里的做法是讲数组数据用 JSON 序列化后,已 VARCHAR 或者 BLOB 的形式存成一列,和其他的数据放在同一个数据表当中。

    8  mmap优化 (未用)

            mmap对I/O性能的提升无需赘言,尤其是对于读操作。SQLite也在OS层封装了mmap的接口,可以无缝地切换mmap和普通的I/O接口。只需配置

    PRAGMA  mmap_size = XXX 

    即可开启mmap。 

        理论上mmap方式能减少内核和用户空间的IO,但在iOS系统中,影响并不大。

    二、测试对比

    参考:www.xxxxxxxxx

    相关文章

      网友评论

        本文标题:Sqlite 数据库的性能

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