泽兴芝士网

一站式 IT 编程学习资源平台

C#避坑指南:提高SQLite 数据写入速度

一、SQLite 写入方法概述

1. 单行插入

直接通过 SQL 语句逐条插入数据到物理文件,每次操作都会触发磁盘 I/O。

- 简单直观

- 频繁磁盘操作

- 最低效的写入方式

2. 批量事务写入

将多个插入操作包裹在事务中执行,通过事务提交减少磁盘 I/O 次数。

- 显著提升写入速度

- 内存缓冲优化

- 推荐的标准批量写入方式

3. 内存缓存序列化

先在内存数据库中操作,最后将完整数据序列化到物理文件。

- 最高效的写入方式

- 需要足够内存容量

- 存在数据丢失风险

二、C# 实现代码示例

环境准备

using System.Data.SQLite;
using System.Diagnostics;
const string DB_FILE_1 = "test1.db";
const string DB_FILE_2 = "test2.db";
const string DB_FILE_3 = "test3.db";
const int TEST_RECORDS = 10000;

1. 单行插入实现

void SingleInsert()
{
  using (var conn = new SQLiteConnection(#34;Data Source={DB_FILE_1};Version=3;"))
  {
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
      cmd.CommandText = "CREATE TABLE Data (Id INTEGER PRIMARY KEY, Value TEXT)";
      cmd.ExecuteNonQuery();
      var sw = Stopwatch.StartNew();
      for (int i = 0; i < TEST_RECORDS; i++)
      {
        cmd.CommandText = #34;INSERT INTO Data (Value) VALUES ('{Guid.NewGuid()}')";
        cmd.ExecuteNonQuery();
      }
      Console.WriteLine(#34;单行插入耗时: {sw.ElapsedMilliseconds}ms");
    }
  }
}

2. 批量事务写入

void BulkInsert()
{
    using (var conn = new SQLiteConnection(#34;Data Source={DB_FILE_2};Version=3;"))
	{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "CREATE TABLE Data (Id INTEGER PRIMARY KEY, Value TEXT)";
        cmd.ExecuteNonQuery();

        using (var transaction = conn.BeginTransaction())
        {
            var sw = Stopwatch.StartNew();
            for (int i = 0; i < TEST_RECORDS; i++)
            {
                cmd.CommandText = #34;INSERT INTO Data (Value) VALUES ('{Guid.NewGuid()}')";
                cmd.ExecuteNonQuery();
            }
            transaction.Commit();
            Console.WriteLine(#34;批量插入耗时: {sw.ElapsedMilliseconds}ms");
        }
    }
}
}

3. 内存缓存序列化

void MemoryCacheInsert()
{
    using (var memConn = new SQLiteConnection("Data Source=:memory:"))
    {
      memConn.Open();
      // 创建内存表
      using (var cmd = memConn.CreateCommand())
      {
        cmd.CommandText = "CREATE TABLE Data (Id INTEGER PRIMARY KEY, Value TEXT)";
        cmd.ExecuteNonQuery();
        // 内存写入
        var sw = Stopwatch.StartNew();
        using (var transaction = memConn.BeginTransaction())
        {
          for (int i = 0; i < TEST_RECORDS; i++)
          {
            cmd.CommandText = #34;INSERT INTO Data (Value) VALUES ('{Guid.NewGuid()}')";
            cmd.ExecuteNonQuery();
          }
          transaction.Commit();
        }
        Console.WriteLine(#34;插入到内存耗时: {sw.ElapsedMilliseconds}ms");
        // 序列化到磁盘
        using (var diskConn = new SQLiteConnection(#34;Data Source={DB_FILE_3};Version=3;"))
        {
          diskConn.Open();
          memConn.BackupDatabase(diskConn, "main", "main", -1, null, 0);
        }
        Console.WriteLine(#34;序列化到磁盘缓存耗时: {sw.ElapsedMilliseconds}ms");
      }
    }
}

三、性能测试对比

测试环境:

  • CPU: i7-1065G
  • RAM: 16GB DDR4
  • SSD: HFM256G
  • 测试数据量:10,000 条记录

测试数据:

测试结果:

1. “事务机制”的影响最为显著,批量写入比单条插入快约 570 倍;

2. “内存操作”相比磁盘操作有约 30% 的性能提升;

3. “序列化到硬盘时间”占总时间的 15%-20%,但整体仍最优。

四、技术选择和适用场景

1. 实时单条写入:配置变更、用户操作日志

2. 批量数据导入:传感器数据、日志批量存储

  • 使用事务包裹的批量插入
  • 建议每 10,000-100,000 条提交一次

3. 高频写入场景:实时数据分析、缓存系统

  • 内存数据库 + 定时序列化
  • 配合异步备份机制

五、总结

通过合理选择写入策略,可以使 SQLite 的写入性能产生数量级的差异。对于大多数 C# 应用场景,建议优先采用事务批量写入方式,在内存敏感场景可结合内存数据库技术。开发者需要根据具体业务需求,在数据安全性和写入性能之间找到最佳平衡点。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言