技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 系统运维 --> 关于sqlite的事务的使用

关于sqlite的事务的使用

浏览:2715次  出处信息

缘起

   sqlite写入500条不大的记录居然要花费20多秒的时间,太慢了!!!

分析

   sqlite是一个非常优秀的嵌入式数据库,读取性能非常好,写入性能就比较差一些,为什么写入性能差呢?下面做了一个测试。

   下面是对500+条记录些操作的系统调用的观察,发现时间基本花费在了fdatasync系统调用上,调用2064次;write系统调用虽然8049次,但是write并不保证逻辑,所以速度很快。

$ strace -c php test.php 
27.688107013702 (耗时27.6s)
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 88.73    0.073919          36      2064           fdatasync
  3.88    0.003231           0      8049           write
  3.77    0.003144           6       516           unlink
  1.12    0.000929           0      6730           fcntl64
  0.90    0.000751           0      9118         3 _llseek
  0.86    0.000720           1      1218        82 open
  0.24    0.000198           0      1143           close
  0.20    0.000167           0      1182           read
  0.16    0.000131           0       520       518 access
  0.05    0.000039           1        42         1 lstat64
  0.04    0.000033           0       194           mmap2
  0.03    0.000027           0        92           munmap
  0.03    0.000021           0        58        49 stat64
  0.00    0.000000           0         1           execve
  0.00    0.000000           0        20           time
  0.00    0.000000           0        21           brk
  0.00    0.000000           0         3         2 ioctl
  0.00    0.000000           0         3           gettimeofday
  0.00    0.000000           0         1           readlink
  0.00    0.000000           0         2           uname
  0.00    0.000000           0        28           mprotect
  0.00    0.000000           0         4           poll
  0.00    0.000000           0         5           rt_sigaction
  0.00    0.000000           0         2           rt_sigprocmask
  0.00    0.000000           0         2           getcwd
  0.00    0.000000           0         1           getrlimit
  0.00    0.000000           0       648           fstat64
  0.00    0.000000           0         4           futex
  0.00    0.000000           0         1           sched_setaffinity
  0.00    0.000000           0         2           sched_getaffinity
  0.00    0.000000           0         1           set_thread_area
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         4           socket
  0.00    0.000000           0         4         2 connect
  0.00    0.000000           0         1           send
  0.00    0.000000           0         1           recvfrom
  0.00    0.000000           0         1           shutdown
  0.00    0.000000           0         5           setsockopt
------ ----------- ----------- --------- --------- ----------------
100.00    0.083310                 31693       657 total

查资料

   http://www.cnblogs.com/KimSky/archive/2011/05/31/2064028.html

   发现: 如果使用事务的方式批量插入数据,效果会有明显改善,因为默认情况下每次写入操作都会落地才返回的(更加安全靠谱),如果使用事务,则批量数据一次性落地。

   修改代码,分析系统调用如下:(发现fdatasync调用12次)

$ strace -c php test.php 
0.20949816703796 (耗时 209ms)
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 71.64    0.000998          83        12           fdatasync
  7.61    0.000106           1       155           read
  5.24    0.000073           0       194           mmap2
  4.16    0.000058           0       195           write
  2.58    0.000036           0       135           fstat64
  1.65    0.000023           0        92           munmap
  1.58    0.000022           1        28           mprotect
  1.51    0.000021           1        42         1 lstat64
  1.44    0.000020          20         1           readlink
  1.29    0.000018           0       238         3 _llseek
  1.29    0.000018           0        58        49 stat64
  0.00    0.000000           0       192        82 open
  0.00    0.000000           0       117           close
  0.00    0.000000           0         3           unlink
  0.00    0.000000           0         1           execve
  0.00    0.000000           0        20           time
  0.00    0.000000           0         7         5 access
  0.00    0.000000           0        21           brk
  0.00    0.000000           0         3         2 ioctl
  0.00    0.000000           0         3           gettimeofday
  0.00    0.000000           0         2           uname
  0.00    0.000000           0         4           poll
  0.00    0.000000           0         5           rt_sigaction
  0.00    0.000000           0         2           rt_sigprocmask
  0.00    0.000000           0         2           getcwd
  0.00    0.000000           0         1           getrlimit
  0.00    0.000000           0        61           fcntl64
  0.00    0.000000           0         4           futex
  0.00    0.000000           0         1           sched_setaffinity
  0.00    0.000000           0         2           sched_getaffinity
  0.00    0.000000           0         1           set_thread_area
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         4           socket
  0.00    0.000000           0         4         2 connect
  0.00    0.000000           0         1           send
  0.00    0.000000           0         1           recvfrom
  0.00    0.000000           0         1           shutdown
  0.00    0.000000           0         5           setsockopt
------ ----------- ----------- --------- --------- ----------------
100.00    0.001393                  1620       144 total

结论:

   1. 借用事务采用批量写入的方式来加速写操作

   2. 如果业务上不能批量操作呢?似乎有一个nosync的sqlite版本(不知道为什么不是一个配置选项)

   参考资料: http://www.sqlite.org/speed.html

   3. 如果数据量太大,可以分多批提交事务,因为事务是需要内存的。(不过,sqlite一般不会存放N个G的数据的,几百MB已经算是比较大的了,这样的数据量内存还是吃的消的)

   参考资料:

   http://www.phpchina.com/archives/view-33876-1.html

   关于sqlite的系列分析文章(可以看看)

   http://www.cnblogs.com/hustcat/archive/2009/02/12/1389448.html

   SQLite的原子提交原理

   http://www.cnblogs.com/vagerent/archive/2008/11/05/1327247.html

建议继续学习:

  1. 分布式系统的事务处理    (阅读:5968)
  2. 在perl中连接和使用sqlite做数据存储    (阅读:5041)
  3. 从Mysql到Sqlite的迁移    (阅读:4175)
  4. 分布式事务性能分析    (阅读:3853)
  5. MySQL数据库分布式事务XA优缺点与改进方案    (阅读:3557)
  6. SQLIte这么娇小可爱,不多了解点都不行啊    (阅读:3480)
  7. Google Megastore系统事务机制    (阅读:2361)
  8. 使用python将Sqlite中的数据直接输出为CVS    (阅读:2307)
  9. MySQL数据库分布式事务XA的实现原理分析    (阅读:2273)
  10. Storm入门教程 第五章 一致性事务    (阅读:1897)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1