使用事务操作SQLite数据批量插入,提高数据批量写入速度,源码讲解

SQLite数据库作为一般单机版软件的数据库,是非常优秀的,我目前单机版的软件产品线基本上全部替换Access作为优选的数据库了,在开发过程中,有时候需要批量写入数据的情况,发现传统的插入数据模式非常慢,几千条数据的写入或者更新可能需要好几分钟时间,而SqlServer则相同的操作可能几秒即可,有无更好的方法来提高它的响应速度呢?答案是有的,就是采用事务提交,默认SQLite的数据库插入操作,如果没有采用事务的话,它每次写入提交,就会触发一次事务操作,而这样几千条的数据,就会触发几千个事务的操作,这就是时间耗费的根源。本文通过详细代码介绍如何使用事务来提高整个批量插入数据的速度,并以实际的Winform开发框架中的字典管理模块的批量插入功能来进行介绍,通过前后速度的对比,使得事务操作提高响应速度更有说服力。

由于一些项目需要,字典管理模块需要批量录入数据,因此改善了我的《Winform开发框架》中的字典管理模块,在字典管理模块增加一个批量添加的功能,如下所示。

对一些诊断的数据录入,一般情况下都可能是几千条的数据,还有可能更多的一些分类字典,那么如果每次都需要等待几分钟或者几十分钟,那么这样的响应体验肯定很差。

为了提高响应速度,我这里使用了事务操作,整个事务操作是基于EnterpriseLibray类库的数据库操作,由于我已经在框架的基类中做了封装,因此我们这里看到整个处理过程即可。

其中MyRegion里面的代码就是遍历每行的数据,构造数据字典对象和排序号,然后调用InsertDictData函数进行数据的录入。其中InsertDictData函数的代码是

        /// <summary>
        /// 使用事务参数,插入数据,最后统一提交事务处理
        /// </summary>
        /// <param name="dictData">字典数据</param>
        /// <param name="seq">排序</param>
        /// <param name="trans">事务对象</param>
        private void InsertDictData(string dictData, string seq, DbTransaction trans)
        {
            if (!string.IsNullOrWhiteSpace(dictData))
            {
                DictDataInfo info = new DictDataInfo();
                info.Editor = LoginID;
                info.LastUpdated = DateTime.Now;
                info.DictType_ID = this.txtDictType.Tag.ToString();
                info.Name = dictData.Trim();
                info.Value = dictData.Trim();
                info.Remark = this.txtNote.Text.Trim();
                info.Seq = seq;

                bool succeed = BLLFactory<DictData>.Instance.Insert(info, trans);
            }
        }

整个插入功能按钮的处理全部代码如下所示。

        private void btnOK_Click(object sender, EventArgs e)
        {
            string[] arrayItems = this.txtDictData.Lines;
            int intSeq = -1;
            int seqLength = 3;
            string strSeq = this.txtSeq.Text.Trim();
            if (int.TryParse(strSeq, out intSeq))
            {
                seqLength = strSeq.Length;
            }

            if (arrayItems != null && arrayItems.Length > 0)
            {
                DbTransaction trans = BLLFactory<DictData>.Instance.CreateTransaction();
                if (trans != null)
                {
                    try
                    {
                        #region MyRegion
                        foreach (string strItem in arrayItems)
                        {
                            if (this.radSplit.Checked)
                            {
                                if (!string.IsNullOrWhiteSpace(strItem))
                                {
                                    string[] dataItems = strItem.Split(new char[] { ',', ',', ';', ';', '/', '、' });
                                    foreach (string dictData in dataItems)
                                    {
                                        #region 保存数据
                                        string seq = "";
                                        if (intSeq > 0)
                                        {
                                            seq = (intSeq++).ToString().PadLeft(seqLength, '0');
                                        }
                                        else
                                        {
                                            seq = string.Format("{0}{1}", strSeq, intSeq++);
                                        }

                                        InsertDictData(dictData, seq, trans);
                                        #endregion
                                    }
                                }
                            }
                            else
                            {
                                #region 保存数据
                                if (!string.IsNullOrWhiteSpace(strItem))
                                {
                                    string seq = "";
                                    if (intSeq > 0)
                                    {
                                        seq = (intSeq++).ToString().PadLeft(seqLength, '0');
                                    }
                                    else
                                    {
                                        seq = string.Format("{0}{1}", strSeq, intSeq++);
                                    }

                                    InsertDictData(strItem, seq, trans);
                                }
                                #endregion
                            }
                        }
                        #endregion

                        trans.Commit();
                        ProcessDataSaved(this.btnOK, new EventArgs());
                        MessageDxUtil.ShowTips("保存成功");
                        this.DialogResult = DialogResult.OK;
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        LogTextHelper.Error(ex);
                        MessageDxUtil.ShowError(ex.Message);
                    }
                }
            }
        }

上面的批量插入,经过前后的测试,2千条数据批量插入SQLite数据库,需要大概3~4分钟左右,如果采用了事务操作,则在1~2秒内写入完成,速度提高不知道多少倍。如果是操作数据比较多的,强烈建议使用事务进行操作,可以给客户很好的体验效果。

如果嫌上面的代码复杂,可以看下面的讲解代码可能就明白了

        using (DbTransaction dbTrans = conn.BeginTransaction())
        {
            using (DbCommand cmd = conn.CreateCommand())
            {
                cmd.CommandText = "INSERT INTO MyTable(MyValue) VALUES(?)";
                DbParameter Field1 = cmd.CreateParameter();
                cmd.Parameters.Add(Field1);
                for (int n = 0; n < 100000; n++)
                {
                    Field1.Value = n + 100000;
                    cmd.ExecuteNonQuery();
                }
            }
        }

上面是一种比较简单原始的事务操作,如果批量插入数据,同样能够起到一样的效果。

本文转自博客园伍华聪的博客,原文链接:使用事务操作SQLite数据批量插入,提高数据批量写入速度,源码讲解,如需转载请自行联系原博主。

时间: 2024-10-22 01:26:26

使用事务操作SQLite数据批量插入,提高数据批量写入速度,源码讲解的相关文章

jdbc批量出入-jdbc批量插入,数据只有一条

问题描述 jdbc批量插入,数据只有一条 我统一10条插入一次,可是最后数据库只有第十条数据,前九条都没有,插入几次都是,怎么办 List backList = new ArrayList(); Connection con = getConnection(); PreparedStatement stat = null; String str= null; int j = 0; for(int i=0;i<list.size();i++){ str = list.get(i); String[

现在项目中有一个这样的需求需要实现这样的窗口,选择多种数据,请问谁有这样的源码。

问题描述 现在项目中有一个这样的需求需要实现这样的窗口,选择多种数据,请问谁有这样的源码. 解决方案 直接用cfiledialog(C++)或者openfiledialog(C#)等. 也可以用toolbar listview combobox button等组合.

MyBatis批量插入(insert)数据操作_java

在程序中封装了一个List集合对象,然后需要把该集合中的实体插入到数据库中,由于项目使用了Spring+MyBatis的配置,所以打算使用MyBatis批量插入,由于之前没用过批量插入,在网上找了一些资料后最终实现了,把详细过程贴出来. 实体类TrainRecord结构如下: public class TrainRecord implements Serializable { private static final long serialVersionUID = -12069604621179

Android实现基于滑动的SQLite数据分页加载技术(附demo源码下载)_Android

本文实例讲述了Android实现基于滑动的SQLite数据分页加载技术.分享给大家供大家参考,具体如下: main.xml如下: <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_settings" android:orderInCategory="100" android:showAs

Android实现基于滑动的SQLite数据分页加载技术(附demo源码下载)

本文实例讲述了Android实现基于滑动的SQLite数据分页加载技术.分享给大家供大家参考,具体如下: main.xml如下: <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_settings" android:orderInCategory="100" android:showAs

CYQ.Data 数据框架 V3.5 开源版本发布(源码提供下载)

 先说几句:    最近一直在忙微博粉丝精灵+微博人气精灵的微博精灵系列软件的事,简单说就是新浪微博营销这块的,提供基于新浪微博的各项服务. 同时也在寻找对网络(微博)营销的才子一起合作创业,感兴趣请Q我. 本人微博地址签名里应该有,这里也重复提一下:http://www.weibo.com/cyqdata   前言:    最近发现研究 CYQ.Data 框架的人比较多,虽然本人一年来没怎么再推这框架了,感觉用户就是喜欢沉淀多一些.年份久一点的. 由于V3.0的开源版本,在Access里可能有

CYQ.Data 数据框架 V4.0 开源版本发布(源码提供下载,秋色园V2.5版本标配框架)

说明的说明:   博客园团队两次移此文出首页,说 这篇文章不属于知识分享型文章,并且有广告嫌疑. 本文的确属于分享型文章,而且分享的知识点比其它文章都多很多,看看网友回复"谢谢分享"就知道是分享型文章了.   所谓广告嫌疑,这东西一被扣上,就很难说的清. 本框架从2007年就始发布在博客园,一直更新维护到现在,其中是有过渡到最新版本是收费,但是仍保留开放很多版本的开源的. 但目前发布的,都是开源的免费版本,再说,涉及到收费就是广告?ext也有收费版本,出现ext相关文章你咋不说是广告?

【android-tips】如何在android应用中插入百度广告(附源码)

(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.介绍    现在游戏中的广告基本上已经成为了游戏创作者的一个重要的收入来源.其实插入广告还是挺简单的,本文选择百度广告联盟作为案例(总觉得百度不会拖欠工资).注:不过,插入广告程序会稍微卡一些,而且真的很耗流量. (本文并不是照抄百度的文档,会很直白哦) 2.代码部分    首先肯定是注册百度广告联盟的账号,和下载sdk.地址:http://munion.baidu.com/     第二步,打开ecli

Sqlite批量插入大数据的例子

这两天被数据库插入批量数据折磨的有点抓狂还好找到了解决方法,话不多说,直接看下面两部分代码: SQLiteDatabase db = dbHelper.getWritableDatabase(); //         LogUtils.i("开始解析*****************"+ new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss").format(new Date()));         for (int i = 0;