Sqlite3常用的插入方法及性能测试

此篇博文是我一开始写在我的csdn(http://blog.csdn.net/roy1261/article/details/51501240)上,以后会慢慢把博文迁移到博客园

最近做到的项目涉及一个大数据量缓存重传,其中要用到的sqlite技术,把自己的学习心得整理了一下。

SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite数据库由于其简单、灵活、轻量、开源,已经被越来越多的被应用到中小型应用中。因此在许多软件中例如(QQ,微信)等许多软件中都有广泛应用。

慢插入-暴力插入

调用sqlite3_exec()函数,会隐式地开启了一个事务,其次,sqlite3_exec() 是sqlite3_perpare(),sqlite3_step(),  sqlite3_finalize()的一个结合,每调用一次这个函数,就会重复的执行这三条语句,对于相同的语句,其中sqlite3_perpare相当于编译sql语句,如果语句相同且重复操作,就会增加很多重复操作。如果插入一条数据,就调该函数一次,事务就会被反复地开启、关闭,会增大IO量。所以当大批量数据插入时,此方法简直无法忍受。

事务插入-显示的开启事务

所谓”事务“就是指一组SQL命令,这些命令要么一起执行,要么都不被执行。如果在插入数据前显式开启事务,插入后再一起提交,则会大大提高IO效率,进而加数据快插入速度

同步关闭模式-synchronous = OFF

当synchronous设置为FULL, SQLite数据库引擎在紧急时刻会暂停以确定数据已经写入磁盘。这使系统崩溃或电源出问题时能确保数据库在重起后不会损坏。FULL synchronous很安全但很慢。

当synchronous设置为NORMAL, SQLite数据库引擎在大部分紧急时刻会暂停,但不像FULL模式下那么频繁。 NORMAL模式下有很小的几率(但不是不存在)发生电源故障导致数据库损坏的情况。但实际上,在这种情况 下很可能你的硬盘已经不能使用,或者发生了其他的不可恢复的硬件错误。

当设置为synchronous OFF时,SQLite在传递数据给系统以后直接继续而不暂停。若运行SQLite的应用程序崩溃, 数据不会损伤,但在系统崩溃或写入数据时意外断电的情况下数据库可能会损坏。另一方面,在synchronous OFF时 一些操作可能会快50倍甚至更多。在SQLite 2中,缺省值为NORMAL.而在3中修改为FULL。

执行前准备-sqlite3_prepare_v2

此方法就是“执行准备”(类似于存储过程)操作,即先将SQL语句编译好,然后再一步一步(或一行一行)地执行。如果采用前者的话,就算开起了事务,SQLite仍然要对循环中每一句SQL语句进行“词法分析”和“语法分析”,这对于同时插入大量数据的操作来说,简直就是浪费时间。因此,要进一步提高插入效率的话,就应该使用此方法

测试结果展示

  1 extern "C"
  2 {
  3     #include "sqlite3.h"
  4 };
  5
  6 #include<sstream>
  7 #include <string>
  8 #include <iostream>
  9 #include <stdlib.h>
 10 #include <ctime>
 11 #include<windows.h>
 12
 13
 14 #define MAX_TEST_COUNT 200
 15
 16 using namespace std;
 17
 18
 19 int main()
 20 {
 21     char cmdCreatTable[256] = "create table SqliteTest (id integer , x integer , y integer, weight real)" ;
 22     sqlite3* db = NULL;
 23     char * errorMessage = NULL;
 24     int iResult = sqlite3_open("SqliteTest.db", &db);
 25     do
 26     {
 27         if (SQLITE_OK != iResult)
 28         {
 29             cout<<"创建InsertTest.db文件失败"<<endl;
 30             break;
 31         }
 32
 33         sqlite3_exec(db,"drop table if exists SqliteTest",0,0,0);
 34
 35         iResult = sqlite3_exec(db, cmdCreatTable, NULL, NULL, &errorMessage);
 36         if (SQLITE_OK != iResult)
 37         {
 38             cout<<"创建表SqliteTest失败"<<endl;
 39             break;
 40         }
 41         DWORD timeStart;
 42         DWORD timeStop;
 43         timeStart = GetTickCount();
 44         for (int i = 0; i< MAX_TEST_COUNT; ++i)
 45         {
 46             stringstream ssm;
 47             ssm<<"insert into SqliteTest values("<<i<<","<<i*2<<","<<i/2<<","<<i*i<<")";
 48             iResult = sqlite3_exec(db,ssm.str().c_str(),0,0,0);
 49         }
 50         timeStop = GetTickCount();
 51         cout<< "直接Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间" << timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
 52
 53         timeStart = GetTickCount();
 54         sqlite3_exec(db,"PRAGMA synchronous = OFF; ",0,0,0);
 55         for(int i = MAX_TEST_COUNT; i < MAX_TEST_COUNT*2; ++i)
 56         {
 57             stringstream ssm;
 58             ssm<<"insert into SqliteTest values("<<i<<","<<i*2<<","<<i/2<<","<<i*i<<")";
 59             sqlite3_exec(db,ssm.str().c_str(),0,0,0);
 60         }
 61         timeStop = GetTickCount();
 62
 63         cout<< "同步写关闭+直接Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间" << timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
 64
 65
 66         timeStart = GetTickCount();
 67         sqlite3_exec(db,"PRAGMA synchronous = FULL; ",0,0,0);
 68         sqlite3_exec(db,"begin;",0,0,0);
 69         for(int i= MAX_TEST_COUNT*2; i< MAX_TEST_COUNT*3; ++i)
 70         {
 71             stringstream ssm;
 72             ssm<<"insert into SqliteTest values("<<i<<","<<i*2<<","<<i/2<<","<<i*i<<")";
 73             sqlite3_exec(db,ssm.str().c_str(),0,0,0);
 74         }
 75         sqlite3_exec(db,"commit;",0,0,0);
 76         timeStop = GetTickCount();
 77         cout<< "事务Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间"<< timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
 78
 79
 80         timeStart = GetTickCount();
 81         sqlite3_exec(db,"PRAGMA synchronous = OFF; ",0,0,0);
 82         sqlite3_exec(db,"begin;",0,0,0);
 83         for(int i = MAX_TEST_COUNT*3; i < MAX_TEST_COUNT*4; ++i)
 84         {
 85             stringstream ssm;
 86             ssm<<"insert into SqliteTest values("<<i<<","<<i*2<<","<<i/2<<","<<i*i<<")";
 87             sqlite3_exec(db,ssm.str().c_str(),0,0,0);
 88         }
 89         sqlite3_exec(db,"commit;",0,0,0);
 90         timeStop = GetTickCount();
 91
 92         cout<< "事务+同步写关闭Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间" << timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
 93
 94         timeStart = GetTickCount();
 95         //sqlite3_exec(db,"PRAGMA synchronous = FULL; ",0,0,0);
 96         sqlite3_exec(db,"begin;",0,0,0);
 97         sqlite3_stmt *stmt;
 98         const char* sql = "insert into SqliteTest values(?,?,?,?)";
 99         sqlite3_prepare(db,sql,strlen(sql),&stmt,0);
100         for(int i = MAX_TEST_COUNT*4; i<MAX_TEST_COUNT*5; ++i)
101         {
102             sqlite3_reset(stmt);
103             sqlite3_bind_int(stmt,1,i);
104             sqlite3_bind_int(stmt,2,i*2);
105             sqlite3_bind_int(stmt,3,i/2);
106             sqlite3_bind_double(stmt,4,i*i);
107             sqlite3_step(stmt);
108          }
109          sqlite3_finalize(stmt);
110          sqlite3_exec(db,"commit;",0,0,0);
111
112          timeStop = GetTickCount();
113          cout<< "事务+执行准备+同步写关闭Insert"<<MAX_TEST_COUNT<<"条数据操作执行时间:"<< timeStart<<"结束时间:"<<timeStop<<"共耗时:"<<timeStop-timeStart<<"ms"<<endl;
114
115
116     }while(0);
117
118     cout<<"插入测试结束"<<endl;
119     Sleep(2000);
120     sqlite3_close(db);
121     system("pause");
122
123 }
时间: 2024-11-05 00:30:34

Sqlite3常用的插入方法及性能测试的相关文章

DOM常用外部插入方法与区别

1.DOM外部插入after()与before() 节点与节点之前有各种关系,除了父子,祖辈关系,还可以是兄弟关系.之前我们在处理节点插入的时候,接触到了内部插入的几个方法,这节我们开始讲外部插入的处理,也就是兄弟之间的关系处理,这里jQuery引入了2个方法,可以用来在匹配I的元素前后插入内容. 选择器 描述 .after(content) 在匹配选择器的每个元素之后插入内容(作为兄弟节点) .before(content) 方法在匹配选择器的元素之前插入内容(作为兄弟节点) before与a

sqlite3常用指令

一.建立数据库 sqlite3.exe test.db 二.双击sqlite-3_6_16目录下的程序sqlite3.exe,即可运行 三.退出 .exit 或者 .quit 四.SQLite支持如下5种数据类型 1.NULL:空值.2.INTEGER:带符号的整型,具体取决有存入数字的范围大小.3.REAL:浮点数字,存储为8-byte IEEE浮点数.4.TEXT:字符串文本.5.BLOB:二进制对象. 五.联系人表格结构如下 create table contact(id integer 

Linux下sqlite3常用命令!!!

sqlite3一款主要用于嵌入式的轻量级数据库,本文旨在为熟悉sqlite3基本命令提供技术文档.备注:本文所有操作均在root用户下进行. 1.安装sqlite3ubuntu下安装sqlite3直接在终端运行命令:#apt-get install sqlite3查看版本信息:#sqlite3 -version 2 .sqlite3常用命令当前目录下建立或打开test.db数据库文件,并进入sqlite命令终端,以sqlite>前缀标识:#sqlite3 test.db 查看数据库文件信息命令(

SVG DOM常用属性和方法介绍

将以Adobe SVG Viewer提供的属性和方法为准,因为不同解析器对JavaScript以及相关的属性和方法支持的程度不同,有些方法和属性是某个解析器所特有的.SVG支持DOM2标准. 12.2.1  文档初始化相关 evt属性 evt表示事件本身,可以通过evt获取与当前事件相关的信息,用户可以在script中定义响应函数,进行相应的处理.它与普通JavaScript脚本中的event基本相同,只不过在普通JavaScript的脚本中简写成“e”. ownerDocument属性 通过引

iPone应用开发 UIView 常用属性和方法

iPone应用程序开发 UIView常用属性和方法 常用属性 alpha 视图的透明度0.0f - 1.0f backgroundColor 视图的背景颜色 subviews 子视图的集合 hidden 视图是否隐藏 tag 视图的唯一标示符,是一个整形数据 superview 视图的父视图 multipleTouchEnabled 是否开启多点触控 userInteractionEnable 是否响应触摸事件 常用方法 - (void)removeFromSuperview; //从父视图中删

UIView常用属性与方法/UIKit继承结构

UIView常用属性与方法 @interface UIView : UIResponder<NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem> /** * 通过一个frame来初始化一个UI控件 */ - (id)initWithFrame:(CGRect)frame; // YES:能够跟用户进行交互 @property(nonatomic,getter=isUserInteractionEnabled) BOOL us

sqlite3 常用命令与 SQL 基本语句

sqlite3 数据库的创建与删除: $ sqlite3 stu.db sqlite3 是小型的数据库,所以直接以单个文件作为一个数据库,在命令行中加入的参数是将要打开并操作的数据库,"stu.db" 是数据库的文件名.如果没有此文件,则创建此文件用来保存将要操作的数据.如果没有参数则不打开任何数据库.因为 sqlite3 以单个文件存储数据库所以,直接删除此文件,数据库就不存在了. sqlite3常用命令: sqlite> .help sqlite> .quit sqli

SQLserver 常用函数适用方法(转载)

SQL Server 常用函数使用方法(持续更新) 之前就想要把一些 SQL 的常用函数记录下来,不过一直没有实行...嘿嘿... 直到今天用到substring()这个函数,C# 里面这个方法起始值是 0,而 SQL 里面起始值是 1.傻傻分不清楚... 这篇博客作为记录 SQL 的函数的使用方法,想到哪里用到哪里就写到哪里... SubString():用于截取指定字符串的方法.该方法有三个参数: 参数1:用于指定要操作的字符串. 参数2:用于指定要截取的字符串的起始位置,起始值为 1 .

Egg中使用egg-mongoose和常用的Mongoose 方法

Mongoose Mongoose就是一套操作MongoDB数据库的接口,而Egg中有对应的插件egg-mongoose. 安装 $ npm install egg-mongoose --save 配置 改变Egg项目中的配置文件{workplace}/config/plugin.js中来启用 egg-mongoose 插件: exports.mongoose = { enable: true, package: 'egg-mongoose', }; Egg连接mongoose 在Egg项目中的