找回密码
 加入
搜索
查看: 6046|回复: 22

[效率算法] 每天处理3W条左右的SQLITE,差不多要两个小时,研究效率写入方法!

  [复制链接]
发表于 2019-11-6 10:10:26 | 显示全部楼层 |阅读模式
本帖最后由 heavenm 于 2019-12-15 15:04 编辑

安全有保障的加速写入方法,缺点就是需要在语句块前后加上
_SQLite_Exec ( $__hdb,'BEGIN;' )
INSERT INTO "test"("%s1") VALUES ("%s1")
INSERT INTO "test"("%s2") VALUES ("%s2")
_SQLite_Exec ( $__hdb,'COMMIT;' )

最简单的写法,缺点就是听说有可能数据损坏!
_SQLite_Exec ( $__hdb,'PRAGMA synchronous = OFF;' )
_SQLite_Exec ( $__hdb,'PRAGMA journal_mode=WAL;' )




 楼主| 发表于 2019-11-6 10:15:36 | 显示全部楼层
本帖最后由 heavenm 于 2019-11-6 11:03 编辑

INSERT INTO "test"("%s") VALUES ("%s")
1000条数据,10秒
1W条 104秒

_SQLite_Exec ( $__hdb,'BEGIN;' )
INSERT INTO "test"("%s") VALUES ("%s")
_SQLite_Exec ( $__hdb,'COMMIT;' )
1W条数据,2秒
 楼主| 发表于 2019-11-6 10:22:54 | 显示全部楼层
INSERT INTO "test" VALUES ("%s")
1W条108秒
 楼主| 发表于 2019-11-6 10:50:25 | 显示全部楼层
在SQLite中,数据库配置的参数都由编译指示(pragma)来实现的,而其中synchronous选项有三种可选状态,分别是full、normal、off。这篇博客以及官方文档里面有详细讲到这三种参数的设置。简要说来,full写入速度最慢,但保证数据是安全的,不受断电、系统崩溃等影响,而off可以加速数据库的一些操作,但如果系统崩溃或断电,则数据库可能会损毁。

SQLite3中,该选项的默认值就是full,如果我们再插入数据前将其改为off,则会提高效率。如果仅仅将SQLite当做一种临时数据库的话,完全没必要设置为full。在代码中,设置方法就是在打开数据库之后,直接插入以下语句:
_SQLite_Exec ( $__hdb,'PRAGMA synchronous = OFF;' )
INSERT INTO "test" VALUES ("%s")
1W条26秒
 楼主| 发表于 2019-11-6 10:58:15 | 显示全部楼层
使用WAL模式

   (1).WAL:Write Ahead Logging,他是数据库中用于实现原子事务的一种机制,从3.7.0版本后引入

   (2).WAL模式主要有两个优点:

      a.读写可以完全并发进行,不会互相阻塞(但是写之间仍然不能并发)

     b.WAL在大多情况下,拥有更好的性能(因为无需每次写入时都要写两个文件)

   (3).Rollback journal机制原理:在修改数据库中的数据前,先将修改所在分页中的数据备份在另一个地方,然后再将修改写入到数据中;如果事务失败,则将备份数据拷贝回来,撤销修改;如果事务成功,则删除备份,提交修改。

   (4).WAL机制原理:修改并不直接写入到数据库文件中,而是写入到另外一个称为WAL的文件中,如果事务失败,wal中的文件会被忽略,撤销修改;如果事务成功,它将在随后的某个时间被写回到数据库文件中,提交修改。

   性能差异主要源于每次事务提交,wal只需要将更新的日志写入磁盘,而delete模式首先要将原始数据拷贝到日志文件中,并进行fsync,然后将修改页写入磁盘,同时也需要fsync,确保数据落盘,并且还要清除日志文件。因此写事务在WAL模式下,只需要一次    fsync,并且是顺序写,而在delete模式下需要至少两次fsync(日志,数据),并且更新的数据离散分布在多个page中,因此可能需要多个fsync。

   WAL使用共享内存技术,因此所有读写进程必须在同一个机器上

   开启WAL模式的方法: 
_SQLite_Exec ( $__hdb,'PRAGMA journal_mode=WAL;' )
1W条17秒
 楼主| 发表于 2019-11-6 10:59:58 | 显示全部楼层
_SQLite_Exec ( $__hdb,'PRAGMA synchronous = OFF;' )
_SQLite_Exec ( $__hdb,'PRAGMA journal_mode=WAL;' )
双剑合并
1W条数据2秒
 楼主| 发表于 2019-11-6 11:02:05 | 显示全部楼层
_SQLite_Exec ( $__hdb,'PRAGMA synchronous = OFF;' )
_SQLite_Exec ( $__hdb,'PRAGMA journal_mode=WAL;' )
_SQLite_Exec ( $__hdb,'BEGIN;' )
INSERT INTO "test"("%s") VALUES ("%s")
_SQLite_Exec ( $__hdb,'COMMIT;' )
三剑合并
1W数据还是差不多2秒
 楼主| 发表于 2019-11-6 11:07:17 | 显示全部楼层
听说还有更快的方法好像!就不研究了,数据量不够,貌似得百万级的数据库吧!
比以前的方法提升了50多倍的效率,很开心了
发表于 2019-11-6 11:09:25 | 显示全部楼层
就问你孤单不孤单
我这贴怕你太孤单
 楼主| 发表于 2019-11-6 11:32:09 | 显示全部楼层
afan 发表于 2019-11-6 11:09
就问你孤单不孤单
我这贴怕你太孤单


好开心看见其他人!
我把这当BLOG写了!
发表于 2019-11-7 05:48:46 | 显示全部楼层
原先也是找到这个办法很高兴的用了
只是怕影响数据完整就只采用了第一方法
结果搞到后来发现数据库加密一直无法成功
只好放弃sqlite 3.dll了
(只有System.Data.SQLite.dll可以但太麻烦><")
所以又回到accdb的怀抱了


 楼主| 发表于 2019-11-7 14:05:14 | 显示全部楼层
w60711 发表于 2019-11-7 05:48
原先也是找到这个办法很高兴的用了
只是怕影响数据完整就只采用了第一方法
结果搞到后来发现数据库加密一 ...

还有这种事情,accdb已经很少有人用了吧!加密倒是没研究,难道accdb效率还会更高么!
最安全的加密应该是用mysql这种中心库吧!

点评

是阿 但是有些小软件是给用户在单机用的,accdb/mdb直接ADODB操作,不用加装其他软件较为方便~  发表于 2019-11-7 23:02
发表于 2019-11-7 15:41:02 | 显示全部楼层
很好奇楼主是干啥工作的....需要性能的可以考虑用其它编译型语言处理性能瓶颈部分。
 楼主| 发表于 2019-11-7 16:52:56 | 显示全部楼层
make2855 发表于 2019-11-7 15:41
很好奇楼主是干啥工作的....需要性能的可以考虑用其它编译型语言处理性能瓶颈部分。

创业进行中哈!
目前做二手手机和群控方面的,要对二手手机价格行情进行分析!
 楼主| 发表于 2019-11-7 18:19:36 | 显示全部楼层

写数据库搞定了,发现读数据库又是一个难题!
现在想的办法是把数据库全部读到内存里,不过数据大概在二十万左右,加载进内存好像没什么太大影响,数据库再大些估计就不行了

$sqliteCommand = StringFormat('SELECT * FROM %s', $t); LIMIT 0,1000


10W左右的数据
内存操作,1秒
数据库查询200秒
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-4-19 16:09 , Processed in 0.081024 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表