找回密码
 加入
搜索
查看: 3113|回复: 14

[AU3基础] SQLITE读取数据写入数组特别慢!原来是ReDim造成的

[复制链接]
发表于 2019-10-29 23:22:19 | 显示全部楼层 |阅读模式
循环读取每次ReDim数组+1

从SQLITE数据库里面读取3W条数据,只要7秒左右!
将结果写入数组确要200秒



排查发现,原来是ReDim的锅,直接预设数组为3万,= =#写数组,一秒都不要!


评分

参与人数 1金钱 +10 收起 理由
guoguo188 + 10 赞一个!

查看全部评分

 楼主| 发表于 2019-10-29 23:26:46 | 显示全部楼层
不要有人和我一样踩坑啊!一直以来我都是用ReDim来循环读取,简直是天坑!
发表于 2019-10-30 11:18:58 | 显示全部楼层
redim放在循环里确实有点慢,au3的redim在改变数组的维度后原数据会丢失,就感觉这个命令意义不是太大,我自己处理的我应该能知道数组预期大小,易语言有个参数是保留原数据就很有意思。比如我正则提取出数组$arr[6] = ["张三","语文80","数学90","李四","语文82","数学77"],可以直接重定义数组为$arr[2][3] = [["张三","语文80","数学90"],["李四","语文82","数学77"]],说的原理是不管是几维数组,数据内容在内存中都是一样的,在处理比较大的数组时,就比重新循环赋值来得快。
发表于 2019-11-4 15:49:11 | 显示全部楼层
差点掉坑里,还好楼主及时提醒
发表于 2019-11-5 09:43:43 | 显示全部楼层
ReDim
调整一个已经存在的数组的大小


ReDim $array[subscript 1]...[subscript n]


参数
$array 要修改大小的数组名.
subscript 要创建的数组中每一维的元素数量,从 0 到 n-1.

注意/说明
关键字 ReDim 的作用类似于 Dim, 但ReDim在调整数组大小时可维持数组元素的值不变而不是删除它们. 数组的维数必须保持一致, 否则旧的数组内容将丢失. 调整数组大小后其作用域(Global 或者 Local)也维持不变.
发表于 2019-12-12 11:03:38 | 显示全部楼层
请教怎样往sqlite插入数据比较快,大概单次数据量1W条,我现在循环一条一条的插入,差不多要400秒
 楼主| 发表于 2019-12-12 15:12:38 | 显示全部楼层
sh1536 发表于 2019-12-12 11:03
请教怎样往sqlite插入数据比较快,大概单次数据量1W条,我现在循环一条一条的插入,差不多要400秒

http://www.autoitx.com/thread-71679-1-1.html
发表于 2019-12-12 19:29:51 | 显示全部楼层
heavenm 发表于 2019-12-12 15:12
http://www.autoitx.com/thread-71679-1-1.html

这个我看过,
开启WAL模式是最快的,但是要求写入和读取要求在同一电脑上
_SQLite_Exec ( $__hdb,'PRAGMA synchronous = OFF;' )这个更不行,我运行了一次,数据库就坏了
开启事件模式试了下,不知道是我用的不对还是怎样,没什么效果
 楼主| 发表于 2019-12-12 21:56:22 | 显示全部楼层
sh1536 发表于 2019-12-12 19:29
这个我看过,
开启WAL模式是最快的,但是要求写入和读取要求在同一电脑上
_SQLite_Exec ( $__hdb,'PRAG ...

_SQLite_Exec ( $__hdb,'BEGIN;' )
INSERT INTO "test"("%s") VALUES ("%s")
_SQLite_Exec ( $__hdb,'COMMIT;' )
我是用这个方法,数据库没有出现损坏的现象,每天写入3W左右的数据测试写入1W数据,2秒
发表于 2019-12-13 01:16:39 | 显示全部楼层
heavenm 发表于 2019-12-12 21:56
_SQLite_Exec ( $__hdb,'BEGIN;' )
INSERT INTO "test"("%s") VALUES ("%s")
_SQLite_Exec ( $__hdb,'C ...

_SQLite_Exec ( $__hdb,'BEGIN;' )  $__hdb换成我的_SQLite_Open返回的数据库句柄
INSERT INTO "test"("%s") VALUES ("%s") 这句我写的是:_SQLite_Exec(INSERT INTO 表名 (列名) VALUES (值)
_SQLite_Exec ( $__hdb,'COMMIT;' )$__hdb换成我的_SQLite_Open返回的数据库句柄


不知道是不是这样用?
 楼主| 发表于 2019-12-13 02:13:29 | 显示全部楼层
sh1536 发表于 2019-12-13 01:16
_SQLite_Exec ( $__hdb,'BEGIN;' )  $__hdb换成我的_SQLite_Open返回的数据库句柄
INSERT INTO "test"(" ...

对就是这样子,你试试就知道了,数据量大你会发现快的不是一点半点
发表于 2019-12-13 09:35:12 | 显示全部楼层
heavenm 发表于 2019-12-13 02:13
对就是这样子,你试试就知道了,数据量大你会发现快的不是一点半点

换了,只快一点点。




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
 楼主| 发表于 2019-12-14 12:58:55 | 显示全部楼层
chzj589 发表于 2019-12-13 09:35
换了,只快一点点。

_SQLite_Exec ( $__hdb,'BEGIN;' )   数据插入开始
把所有的INSERT都写这里面
_SQLite_Exec ( $__hdb,'COMMIT;' )数据插入结束

你不会是单条这样子写吧!
发表于 2019-12-19 21:20:32 | 显示全部楼层
我想到了另外一种做法:
先定义1W行数组,
每次查询时,先判断循环了多少次,如果超过1W次,则Redim增加1W行
全部查询完后再去掉空行

高效去掉空行可以参考这个帖子的7楼:
http://www.autoitx.com/forum.php ... hlight=%CA%FD%D7%E9

这样查询10W条数据,Redim次数只有9次
 楼主| 发表于 2019-12-20 00:40:32 | 显示全部楼层
sh1536 发表于 2019-12-19 21:20
我想到了另外一种做法:
先定义1W行数组,
每次查询时,先判断循环了多少次,如果超过1W次,则Redim增加1 ...

去掉空数组就简单了,只要有个计数,一共累计多少数据,直接redim就OK了
不过我现在改用这个方式,根本就不需要redim了
直接数据库操作了
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-11-16 10:15 , Processed in 0.075516 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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