You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中SQLiteDataAdapter批量插入性能低下问题求助

问题:SQLiteDataAdapter批量插入失败,如何提升JSON数据插入SQLite的效率?

我有一个包含约25-30K条数据的JSON文件,需要存入SQLite数据库。使用SQLiteDataAdapter通过DataTable插入15K条数据耗时约35分钟,当前UpdateBatchSize为1,尝试修改时触发"Specified method is not supported"异常。以下是我的Update方法代码:

public async Task<bool> SaveTable() { 
    SQLiteDataAdapter data_adapter = null; 
    try { 
        data_adapter = new SQLiteDataAdapter(sql_cmd); 
        data_adapter.UpdateBatchSize = 10; 
    } catch (Exception e) { 
        Console.WriteLine("Exception Thrown: " + e.Message); 
        return false; 
    } 
    try { 
        SQLiteCommandBuilder cmd_bldr = new SQLiteCommandBuilder(data_adapter); 
        data_adapter.InsertCommand = cmd_bldr.GetInsertCommand(); 
        Console.WriteLine(data_adapter.InsertCommand.CommandText); 
        data_adapter.AcceptChangesDuringUpdate = true; 
        data_adapter.UpdateCommand = data_adapter.InsertCommand; 
    } catch (Exception e) { 
        Console.WriteLine("Exception Thrown: " + e.Message); 
        return false; 
    } 
    try { 
        var size = data_adapter.UpdateBatchSize; 
        Console.WriteLine("Updating Table. Batch Size: " + size); 
        var rows_updated = data_adapter.Update(data_table); 
        Console.WriteLine("Rows Updated: " + rows_updated.ToString()); 
        data_adapter.Dispose(); 
    } catch(Exception e) { 
        Console.WriteLine("Exception Thrown: " + e.Message); 
        return false; 
    } 
    return true; 
}

请问是否可以修改UpdateBatchSize,或者有其他方法提升每秒插入数据的次数?


解决方案

首先得明确:SQLiteDataAdapter并不支持批量更新(UpdateBatchSize),这就是你触发"Specified method is not supported"异常的原因——这个组件的设计就没实现批量操作的功能,别在这上面浪费时间了。

接下来给你几个能大幅提升插入效率的方法,按优先级排序:

1. 使用事务 + 批量SQL语句

这是提升SQLite插入速度最有效的手段之一,原理是把所有插入操作放在一个事务里(SQLite默认每一条语句都开启一个事务,开销极大),同时拼接批量插入的SQL(比如INSERT INTO table (col1, col2) VALUES (val1,val2), (val3,val4), ...)。

举个简单的实现思路:

  • 先把DataTable里的行分组,每组比如1000条(别太大,避免SQL语句过长)
  • 开启一个SQLite事务
  • 对每个分组,拼接成一条批量插入的SQL命令,执行
  • 最后提交事务

代码示例片段:

using (var conn = new SQLiteConnection(yourConnectionString))
{
    conn.Open();
    using (var transaction = conn.BeginTransaction())
    {
        var command = conn.CreateCommand();
        command.Transaction = transaction;
        
        // 分组处理DataTable行
        int batchSize = 1000;
        for (int i = 0; i < data_table.Rows.Count; i += batchSize)
        {
            var batchRows = data_table.Rows.Cast<DataRow>().Skip(i).Take(batchSize);
            // 拼接批量INSERT语句(实际项目一定要用参数化,避免SQL注入!)
            var valuesClauses = new List<string>();
            foreach (var row in batchRows)
            {
                var param1 = command.CreateParameter();
                param1.ParameterName = $"@val1_{i}";
                param1.Value = row["Col1"];
                var param2 = command.CreateParameter();
                param2.ParameterName = $"@val2_{i}";
                param2.Value = row["Col2"];
                command.Parameters.Add(param1);
                command.Parameters.Add(param2);
                valuesClauses.Add($"({param1.ParameterName}, {param2.ParameterName})");
            }
            command.CommandText = $"INSERT INTO YourTable (Col1, Col2) VALUES {string.Join(", ", valuesClauses)}";
            await command.ExecuteNonQueryAsync();
            command.Parameters.Clear();
        }
        
        transaction.Commit();
    }
}

2. 临时调整SQLite同步模式

SQLite默认的同步模式是FULL,安全性拉满但写入速度慢。如果你的场景可以接受短暂降低同步级别(比如插入完成后能验证数据完整性),可以临时改成OFF或NORMAL,插入结束后再恢复:

using (var conn = new SQLiteConnection(yourConnectionString))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        // 临时降低同步级别
        cmd.CommandText = "PRAGMA synchronous = NORMAL;";
        await cmd.ExecuteNonQueryAsync();
        
        // 执行批量插入操作...
        
        // 恢复默认同步模式
        cmd.CommandText = "PRAGMA synchronous = FULL;";
        await cmd.ExecuteNonQueryAsync();
    }
}

3. 启用WAL日志模式

启用Write-Ahead Logging(WAL)模式可以让SQLite支持并发读写,同时显著提升写入性能。这个设置会持久化到数据库文件,只需执行一次:

using (var conn = new SQLiteConnection(yourConnectionString))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "PRAGMA journal_mode = WAL;";
        await cmd.ExecuteNonQueryAsync();
    }
}

4. 跳过DataTable中转

DataTable是比较重的组件,如果能直接把JSON序列化为实体类列表,再直接操作实体类进行批量插入,会比通过DataTable中转更快。比如用System.Text.Json或Newtonsoft.Json解析JSON到List<YourModel>,再按上面的批量方式插入。

最后再提醒一句:所有涉及外部输入的数据,一定要用参数化查询,绝对不能直接拼接SQL字符串,避免SQL注入风险!


内容的提问来源于stack exchange,提问作者Moth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:28:27