• Sqlite大数据写入性能优化


      众所周知,Sqlite是一个轻量级的数据库,仅仅需要一个exe文件就能运行起来。在处理本地数据上,我比较喜欢选择使用它,不仅是因为他与sql server有着比较相近的语法,还因为它不需要安装,仅需要通过命令行就能启动了,而且他在处理大数据时,性能比sql server好很多,好吧这里不继续争论性能优劣。

      首先,这次的问题是在一次项目中遇到的,项目要求能大量导入数据,而且由于项目性质(轻便,本地化),所以我选择sqlite来存放数据。

      第一版代码:

    1 StringBuilder sql = new StringBuilder();
    2 foreach (DataRow dr in dt.Rows)
    3 {
    4     sql.Append("INSERT INTO Info (Name,Code) VALUES('"+dr[0]+"','"+dr[1]+"') 
    ");    
    5 }
    6 sqlHelper.SqliteHelper.ExecuteNonQuery( sql.ToString(), CommandType.Text);
    View Code

      从上面的代码看来,我没有进行任何优化工作,我用这种方式插入了1万条数据用了1分多钟,可见优化的重要性(百万级数据跑起来...不敢想象)。

      开启事务:

    1 StringBuilder sql = new StringBuilder();
    2 sql.Append("BEGIN;");//开启事务
    3 foreach (DataRow dr in dt.Rows)
    4 {
    5      sql.Append("INSERT INTO Info (Name,Code) VALUES('"+dr[0]+"','"+dr[1]+"') 
    ");    
    6 }
    7 sql.Append("COMMIT;");//提交事务
    8 sqlHelper.SqliteHelper.ExecuteNonQuery( sql.ToString(), CommandType.Text);
    View Code

          由于sqlite的数据操作实质上是对于其数据文件的IO操作,频繁的插入数据会导致文件IO经常开闭,非常损耗性能能。事务作用便是使数据先缓存在系统中,提交事务时便提交所有的更改到数据文件,此时数据文件的IO只需要开闭一次,且避免了长期占用文件IO所导致性能低下的问题。此时,开启事务处理后性能上虽然有了大幅度的提升,但是结果仍旧不理想,哪还有什么在影响着性能呢?下面尝试开启预处理来解决问题。

      开启预处理:

     1  public static int ExecuteNonQuery(string commandText, CommandType commandType)
     2         {
     3             int result = 0;
     4             if (commandText == null || commandText.Length == 0)
     5                 throw new ArgumentNullException("sql语句为空");
     6             using (SQLiteConnection con = new SQLiteConnection(connectionString))
     7             {
     8                 SQLiteCommand cmd = new SQLiteCommand();
     9                 cmd.Connection = con;
    10                 cmd.CommandText = commandText;
    11                 cmd.Prepare();//开启预处理
    12                 try
    13                 {
    14                     result = cmd.ExecuteNonQuery();
    15                 }
    16                 catch (Exception ex)
    17                 {
    18                     throw ex;
    19                 }
    20             }
    21             return result;
    22         }
    23                     
    View Code

      预处理的原理就是将一条语句先预编译到数据库,下次再次执行相同的语句时,就不用再次编译,节省了大量的时间。由此看来,代码似乎还没有优化完成。就第一版代码来说,由于批量插入的数据不尽相同,所以数据库会多次编译插入语句,性能会损耗非常多,也就造成插入需要的时间会比较多。有没有一条语句是可以循环使用的?答案是有的,使用参数化传值,就能使每一次的插入的sql语句都是相同的。

      参数化(数据库帮助类那边我就不写了):

     1 StringBuilder sql = new StringBuilder();
     2 SQLiteParameter[] sp = new SQLiteParameter[2];
     3 foreach (DataRow dr in dt.Rows)
     4 {
     5 sql.Clear();
     6 sql.Append("INSERT INTO Info (Name,Code) VALUES(@Name,@Code) 
    ");  
     7 sps[0] = new SQLiteParameter("@p1", dr["Name"]);
     8 sps[1] = new SQLiteParameter("@p2", dr["Code"]);
     9 sqlHelper.SqliteHelper.ExecuteNonQuery(sql.ToString(),sp, CommandType.Text);  
    10 }
    View Code

      经过一系列优化处理后,插入1万条数据只需要不到1秒,性能得到了极大的提升。

      另外,本人新手,如有不对,望不吝指教。

  • 相关阅读:
    Android 4.2开发环境搭建
    ManagementFactory cannot be resolved
    html css鼠标样式,鼠标形状
    开普勒三定律
    Apache CXF简介
    C++学习基础八——重载输入和输出操作符
    C++学习基础七——深复制与浅复制
    C++学习基础六——复制构造函数和赋值操作符
    C++学习基础五之函数参数——形参
    C++学习基础四——顺序容器和关联容器
  • 原文地址:https://www.cnblogs.com/yisen-code/p/6897524.html
Copyright © 2020-2023  润新知