SQLite数据库插入数据优化(swift)
来源:互联网 发布:在线源码查看 编辑:程序博客网 时间:2024/06/05 18:24
第一种讨论的是正常的插入:
func insertStu() -> Bool { //字符串类型,一定要加'' let sql = "insert into t_person(name,age,score) values ('\(name)',\(age),\(score))" return SQLiteTool.shareinstance.execSQlite(sql) }
//执行语句
// 参数1: 就是一个已经打开的数据库 // 参数2: sql字符串 // 参数3: 回调代码块 nil // 参数4: 参数3 中的参数1 nil // 参数5: 错误信息 func execSQlite(sql : String) -> Bool { return (sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK) }
如果有10000条数据需要加到数据库中,通过上面这个方式插入,实测时间为():
5.88269501924515 5.76592200994492 5.82355201244354 5.48133200407028 6.22769200801849 6.8999969959259(多次测试数据)
说明:不同的机器,测试时间不同,这是纵向的,在同一台机器上测试是横向的,不同的机器测试的时间不同并不能掩盖优化后的明显效果;
使用下面方法对插入10000条数据执行时间的计算:
let startTime = CFAbsoluteTimeGetCurrent()let endTime = CFAbsoluteTimeGetCurrent()print(endTime - startTime)
本文分为两层优化,第一层是使用sqlite3_exec内部实现原理进行直接插入数据,第二层是对事物的优化;
sqlite3_exec函数内部是对”准备语句”的包装,而接下来我们将使用参数绑定的方式,进行插入操作;
参数绑定:
1>创建准备语句
2>绑定参数
3>执行
4>重置
4>销毁
第二种插入方法:参数绑定
//0.固定写法 let sql = "insert into t_person(name,age,score) values (?,?,?)" //1.创建准备语句 //只有调用SQLiteTool就会开启一个数据库,这个数据库就是SQLiteTool.shareinstance.db let db = SQLiteTool.shareinstance.db var tempDB : COpaquePointer = nil //准备语句函数 if sqlite3_prepare_v2(db, sql, -1, &tempDB, nil) != SQLITE_OK{ print("编译失败") }else{ print("编译成功") } let startTime = CFAbsoluteTimeGetCurrent() //模拟大数据插入 for _ in 0..<10000 { //2.绑定 // 不安全的按位进行转换 // 一定要注意,必须明确的确定, 最终的值是什么类型,才能进行转换 // 否则,崩溃! // 参数1: 需要转换的额值 // 参数2: 代表, 想要转换成为的类型 let sqlites_type = unsafeBitCast(-1, sqlite3_destructor_type.self) // 绑定姓名 // 参数1: 准备语句 // 参数2: 绑定的索引(索引, 从1开始) // 参数3: 绑定的值 // 参数4: 代表参数三取出多少长度 -1自动计算 // 参数5: 代表, 参数的处理方式 // #define SQLITE_STATIC ((sqlite3_destructor_type)0) // 代表, 把参数当做一个静态的值, 不会被释放(内部处理, 不对参数做任何的引用) // #define SQLITE_TRANSIENT (()-1) // 代表, 把参数当做是一个临时的值, 有可能会被释放, (内部处理, 对参数做一次引用, 然后, 在合适的地方, 释放掉) sqlite3_bind_text(tempDB, 1, name, -1, sqlites_type) //绑定年龄 sqlite3_bind_int(tempDB, 2, age) //绑定分数 sqlite3_bind_double(tempDB, 3, score) //3.执行 if sqlite3_step(tempDB) != SQLITE_DONE{ print("执行失败") return } //4.重置 //将绑定的值清空 sqlite3_reset(tempDB) } //任务执行完毕后将大门关闭 SQLiteTool.shareinstance.commitTransaction() let enTime = CFAbsoluteTimeGetCurrent() print(enTime - startTime) //5.销毁 sqlite3_finalize(tempDB)
因为创建准备语句和销毁只需要执行一次,所以只在第2步~第4步之间进行时间计算;实测时间为:
5.37796801328659 5.0898619890213 5.47358798980713(多次测试数据) 和使用sqlite3_exec函数的时间稍微好一点,好在的地方是不用每次执行操作都要创建准备语句和销毁,但是优化的效果不明显,接下来进行进一步优化;
SQLite数据库的事务优化:
在使用参数绑定这种方式插入数据的时候,对于每一条数据,系统都会默认开启一个事务进行处理,处理完毕后再关闭事务,处理下一条数据的时候,就会重新开启一个事务,而一个事务是可以处理很多数据的,这里是重复开启事务,浪费性能;
事务就像一扇大门,如果有一个人想要进去,就要开门,进去后关门,然后下一个人还要再开门关门;如果只开启一一次大门,等人都进去了再关门,就会节省很多时间;
当手动开启和关闭事务的时候,系统就不再默认开启关闭,一个注意点就是,手动开启和关闭要成对的;不然会出问题;
数据库工具类中定义两个方法用来实现’开门’和’关门’:
func benginTransaction() -> Void { let sql = "begin transaction" execSQlite(sql) } func commitTransaction() -> Void { let sql = "commit transaction" execSQlite(sql) }
接下来对上面的参数绑定代码进行改进:
注意:这里的关闭’大门’,其实是提交事务;
//0.准备语句 let sql = "insert into t_person(name,age,score) values (?,?,?)" //1.创建准备语句 //只有调用SQLiteTool就会开启一个数据库,这个数据库就是SQLiteTool.shareinstance.db let db = SQLiteTool.shareinstance.db var tempDB : COpaquePointer = nil if sqlite3_prepare_v2(db, sql, -1, &tempDB, nil) != SQLITE_OK{ print("编译失败") }else{ print("编译成功") } let startTime = CFAbsoluteTimeGetCurrent() //执行任务前,将'大门'打开 //如果手动开启,则系统将不再自动开启关闭 SQLiteTool.shareinstance.benginTransaction() //模拟大数据插入 for _ in 0..<10000 { //2.绑定 // 不安全的按位进行转换 // 一定要注意,必须明确的确定, 最终的值是什么类型,才能进行转换 // 否则,崩溃! // 参数1: 需要转换的额值 // 参数2: 代表, 想要转换成为的类型 let sqlites_type = unsafeBitCast(-1, sqlite3_destructor_type.self) // 绑定姓名 // 参数1: 准备语句 // 参数2: 绑定的索引(索引, 从1开始) // 参数3: 绑定的值 // 参数4: 代表参数三取出多少长度 -1自动计算 // 参数5: 代表, 参数的处理方式 // #define SQLITE_STATIC ((sqlite3_destructor_type)0) // 代表, 把参数当做一个静态的值, 不会被释放(内部处理, 不对参数做任何的引用) // #define SQLITE_TRANSIENT (()-1) // 代表, 把参数当做是一个临时的值, 有可能会被释放, (内部处理, 对参数做一次引用, 然后, 在合适的地方, 释放掉) sqlite3_bind_text(tempDB, 1, name, -1, sqlites_type) //绑定年龄 sqlite3_bind_int(tempDB, 2, age) //绑定分数 sqlite3_bind_double(tempDB, 3, score) //3.执行 if sqlite3_step(tempDB) != SQLITE_DONE{ print("执行失败") return } //4.重置 //将绑定的值清空 sqlite3_reset(tempDB) } //任务执行完毕后将'大门'关闭 SQLiteTool.shareinstance.commitTransaction() let enTime = CFAbsoluteTimeGetCurrent() print(enTime - startTime) //5.销毁 sqlite3_finalize(tempDB)
手动开启事务和提交事务后测试插入10000条数据的时间为:
0.0318340063095093 0.0334579944610596 0.0285890102386475 效果是很突出的(多次实测数据)
0 0
- SQLite数据库插入数据优化(swift)
- sqlite大量数据插入的优化
- sqlite大量数据插入优化总结
- android SQLite大数据插入优化
- anroid Sqlite批量插入数据优化方法
- sqlite批量插入数据优化(转载)
- Android开发之SQLite插入数据优化
- sqlite批量插入数据性能优化
- SQLite数据库数据查询DQL(swift)
- SQLite数据库如何批量插入数据?
- Android批量插入数据到SQLite数据库
- Android批量插入数据到SQLite数据库
- Android批量插入数据到SQLite数据库
- Android--批量插入数据到SQLite数据库
- Android批量插入数据到SQLite数据库
- SQLite初识(四)数据库插入数据
- android sqlite数据 插入1000条数据优化
- Android SQLite 插入优化
- Android 基础总结:开篇
- 编译错误:multiple types in one declaration
- Android Studio 2.2 Preview - New UI Designer & Constraint Layout
- 探讨read的返回值的三种情况
- [从头学数学] 第217节 带着计算机去高考(九)
- SQLite数据库插入数据优化(swift)
- 个人网址导航
- 关于uc/os-ii在c51上的移植总结
- /proc/sysrq-trigger文件
- asp.net学习之Repeater控件
- virtualbox 启动时Kernel driver not installed (rc=-1908) 错误的解决方法
- Android设计模式之建造者模式——AlertDialog
- 嵌入式开发中添加支持harfbuzz-ng所支持的设备
- Markdown中使用LaTeX