C#:SQLite大量插入的效率问题
QLite大量插入的效率问题
http://www.cnblogs.com/rader/articles/1543760.html
这两天再做一个数据转换的程序,讲原来用二进制形势存储的数据转换到SQLite数据库中去。记录总共有1千万多点。开发使用的是.net framework 3.5 sp1的环境,所以直接使用了EntityFramework方便数据库的操作。EntityFramework倒是省了一些事情,可是效率上让人无法忍受。整个程序运行一次花了40多分钟。利用EntityFramework,首先从数据库生成模型,然后我这样来保存数据:
1
2
3
4
5
6
7
8
|
using (GameSetEntities gse = new GameSetEntities(CreateConnection()))
{
foreach ( var ticket in tickets)
{
gse.AddToShuffledTicketSet(ticket);
}
gse.SaveChanges( true );
}
|
Ticket是我要插入数据库中的记录。一千多万条记录,我是分成5000条一批进行处理的。5000条记录先被添加到GameSetEntities(DataContext)中,然后进行提交。
利用StopWatch,我记录了这5000条记录插入数据库所消耗的时间,平均是1.1秒。(2080 * 1.1)/60 大约是36分钟,也就是说整个程序的运行时间中有80%多的时间是花在了数据库的插入操作上。插入5000条记录平均花费1.1秒,这个速度实在太慢了。我开始怀疑是不是EntityFramework效率问题?既然这样那就比比看吧,看看纯粹的ado.net代码是不是比它快。下面是纯手工的数据库操作代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
using (DbConnection conn = DbProviderFactories.GetFactory( "System.Data.SQLite" ).CreateConnection())
{
conn.ConnectionString = "Data Source = " + m_datasourceFile + ";Version = 3" ;
using (SQLiteCommand insertRngCmd = (SQLiteCommand)conn.CreateCommand())
{
insertRngCmd.CommandText = @"INSERT INTO shuffled_tickets (ticket_idx, seed, win_credits, [timestamp], redeemed, prog_levels)
VALUES (@ticket_idx, @seed, @win_credits, @timestamp, @redeemed, @prog_levels)" ;
conn.Open();
foreach ( var ticket in tickets)
{
insertRngCmd.Parameters.AddWithValue( "@ticket_idx" , ticket.ticket_idx);
insertRngCmd.Parameters.AddWithValue( "@seed" , ticket.seed);
insertRngCmd.Parameters.AddWithValue( "@win_credits" , ticket.win_credits);
insertRngCmd.Parameters.AddWithValue( "@timestamp" , ticket.timestamp);
insertRngCmd.Parameters.AddWithValue( "@redeemed" , ticket.redeemed);
insertRngCmd.Parameters.AddWithValue( "@prog_levels" , ticket.prog_levels);
insertRngCmd.ExecuteNonQuery();
}
}
}
|
这样的代码一运行,发现速度更慢了,5000记录居然要20秒的时间……看来问题不是在这里。
Google一番之后,在Sqlite.net ADO Provider的论坛里发现这篇文章:Fastest Bulk Inserts.在最后一个例子“Fastest universal way to insert data using standard ADO.NET constructs”中作者提到“100,000 inserts on my machine in 1.4 seconds”--10万条记录插入耗时1.4秒。我才5000条不应该需要20秒那么慢的(用EntityFramework需要1.1秒,后来分析应该是内部使用了批量插入操作),看来是我的代码写的有问题。仔细阅读了作者给的例子之后发现,我们代码的差别主要在于事务的使用上。作者给的例子使用事务一次性提交10万条记录,而我的代码没有使用事务,而是每次提交。于是我改写了一下我的代码,也加上事务进行提交:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
using (DbConnection conn = DbProviderFactories.GetFactory( "System.Data.SQLite" ).CreateConnection())
{
conn.ConnectionString = "Data Source = " + m_datasourceFile + ";Version = 3" ;
using (SQLiteCommand insertRngCmd = (SQLiteCommand)conn.CreateCommand())
{
insertRngCmd.CommandText = @"INSERT INTO shuffled_tickets (ticket_idx, seed, win_credits, [timestamp], redeemed, prog_levels)
VALUES (@ticket_idx, @seed, @win_credits, @timestamp, @redeemed, @prog_levels)" ;
conn.Open();
var transaction = conn.BeginTransaction();
foreach ( var ticket in tickets)
{
insertRngCmd.Parameters.AddWithValue( "@ticket_idx" , ticket.ticket_idx);
insertRngCmd.Parameters.AddWithValue( "@seed" , ticket.seed);
insertRngCmd.Parameters.AddWithValue( "@win_credits" , ticket.win_credits);
insertRngCmd.Parameters.AddWithValue( "@timestamp" , ticket.timestamp);
insertRngCmd.Parameters.AddWithValue( "@redeemed" , ticket.redeemed);
insertRngCmd.Parameters.AddWithValue( "@prog_levels" , ticket.prog_levels);
insertRngCmd.ExecuteNonQuery();
}
transaction.Commit();
}
|
结果5000条记录的插入时间由原来的1.1秒变为0.09秒,这是一个非常大的提升。
但是为什么加上一个事务之后的差别这么大呢?我翻了翻Sqlite的文档,“Database Speed Comparison”里有解释:
在“Test1:1000 INSERTS”下面有一句话:……“In this test, each SQL statement is a separate transaction so the database file must be opened and closed and the cache must be flushed 1000 times”……
在“Test 2:25000 INSERT in a transaction”下面有另外一句话:……“When all the INSERTs are put in a transaction, SQLite no longer has to close and reopen the database or invalidate its cache between each statement. ”……
从上面两句话看来,没有事务的时候,SQLite的插入操作使用了太多的IO操作,而是用事务的话,只需要一次IO。
C#:SQLite大量插入的效率问题相关推荐
- SQLITE高速插入数据
SQLITE数据库在写入数据时,写入数据库的速度非常重要,如果写入的速度慢,有大量数据待写入时,一是会造成程序卡顿,二是数据写入会失败,数据缺失. 传统的往数据库里插入数据是执行一条SQL语句,多条数 ...
- android SQLite 批量插入数据慢的解决方案 (针对于不同的android api 版本)
android SQLite 批量插入数据慢的解决方案 (针对于不同的android api 版本) 参考文章: (1)android SQLite 批量插入数据慢的解决方案 (针对于不同的andro ...
- SQLite解决插入大量数据速度慢的问题
SQLite解决插入大量数据速度慢的问题 背景 在重构公司项目中发现,公司以前代码中将大量数据插入SQLite数据库,速度非常慢,几千条居然需要将近1分钟: 解决方法 知识背景 事务(Transact ...
- SQLite批量插入效率
一.循环单条数据插入 SQLite插入单条数据效率并不高,原因是: Because it does not have a central server to coordinate access, SQ ...
- anroid Sqlite批量插入数据优化方法
SQLite的数据库本质上来讲就是一个磁盘上的文件,所以一切的数据库操作其实都会转化为对文件的操作,而频繁的文件操作将会是一个很好时的过程,会极大地影响数据库存取的速度. 例如:向数据库中插入100万 ...
- sqlite c++插入 timestamp_Dqlite,基于sqlite 高可用(HA)数据库
原文发表于我的博客, 特此版权声明 noosphere.site: Dqlite,基于sqlite 高可用(HA)数据库 csdn : Dqlite,基于sqlite 高可用(HA)数据库 k3s之前 ...
- 颠覆:链表在删除和插入的效率一定优于数组吗?
在大二我们学校的计算机大赛中,出了一道题目:要求证明对于数组和链表进行500次随机访问,比较他们的运行时间.这道题目对于我们程序员来说,可能潜在的答案是链表肯定是快的,但是结果呢? 其实数组在计算机中 ...
- SQLite大批量插入性能优化
SQLite作为轻量级,零安装的数据库,用在小型桌面应用程序上特别合适. 网上搜了一下,貌似在程序中无法直接从格式化文本或CSV文件导入SQLite,只能逐条insert,这一点比起SQL SERVE ...
- android sqlite批量操作,Android: SQLite批量插入数据的最佳实践
大家都知道,Android里数据库用的是SQLite.在实际开发过程中,我们有时候会遇到批量插入数据的场景.这篇文章给大家分享一个小技巧,让批量插入数据达到最快的目的. 首先,我先创建一个Table, ...
- 安卓mysql插入数据_【11-25求助】关于Android 的SQLite数据库插入数据报错问题
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 运行程序,不知道为何点插入数据按钮会报错,请万能的吧友帮我看看,谢谢,不废话,直接上代码 MainActivity.java package com.ex ...
最新文章
- c语言编写pdf,编写并运行C语言程序.pdf
- 我向面试官讲解了单例模式,他对我竖起了大拇指
- upstream directive is not allowed here in
- docker rabbitmq_RabbitMQ消息中间件快速入门
- CSDN重推软件下载频道 软件发布又有新阵地
- 【转】Latex入门教程
- c语言mud游戏制作,MUD游戏制作工具下载
- CountDownLatch 用法和源码解析
- 日本知名动画公司东映动画加入 The Sandbox 元宇宙
- Java实现23种设计模式教程(作者原创)
- 16 最小二乘法 - 数据分析的瑞士军刀
- 米饭里加点它,4大病症全没了!一定要告诉家里做饭的TA
- Quartus II的破解之道
- PaddlePaddle 系列之三行代码从入门到精通
- ESP32 开发笔记(八)ESP32 MP3 播放器
- 计算机科学在本质上源自,计算机与信息技术基础(第4版)第1章.ppt
- HighTec编译器提高编译速度
- dhcp地址分配信息是什么_DHCP动态网段分配|必看
- 时间序列深度学习:状态 LSTM 模型预測太阳黑子(一)
- 6S大气传输模型修改源码添加、自定义CASI传感器光谱响应