一、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# 应用场景,建议优先采用事务批量写入方式,在内存敏感场景可结合内存数据库技术。开发者需要根据具体业务需求,在数据安全性和写入性能之间找到最佳平衡点。