之前在项目中使用了sqlite数据库,当日志变大时,执行CRUD操作就会变慢
后来尝试删除7天前的记录进行优化
delete from XX_CollectData where CreateTime<='2024-01-24'
发现sqlite文件的大小就没有变化,delete命令只是逻辑删除,所在的文件的字节码仍然还在,优化效果仍不明显。
后来使用真空命令VACUUM,发现文件大小确实变小了。
VACUUM
SQLite Vacuum
VACUUM 命令通过复制主数据库中的内容到一个临时数据库文件,然后清空主数据库,并从副本中重新载入原始的数据库文件。这消除了空闲页,把表中的数据排列为连续的,另外会清理数据库文件结构。
如果表中没有明确的整型主键(INTEGER PRIMARY KEY),VACUUM 命令可能会改变表中条目的行 ID(ROWID)。VACUUM 命令只适用于主数据库,附加的数据库文件是不可能使用 VACUUM 命令。
如果有一个活动的事务,VACUUM 命令就会失败。VACUUM 命令是一个用于内存数据库的任何操作。由于 VACUUM 命令从头开始重新创建数据库文件,所以 VACUUM 也可以用于修改许多数据库特定的配置参数。
相关测试程序类【C#代码】
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SQLite;
using System.Linq;
using System.Text;
namespace SnakeSqliteDemo
{
/// <summary>
/// 作者:斯内科
/// 时间:2024-01-24
/// 功能:sqlite数据库操作类
/// </summary>
public class SqliteDbHelper
{
/// <summary>
/// 连接字符串
/// </summary>
private string m_strConnectString = string.Empty;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="strDbPath">SQLite数据库文件路径</param>
public SqliteDbHelper(string strDbPath)
{
this.m_strConnectString = "Data Source=" + strDbPath;
}
/// <summary>
/// 创建SQLite数据库文件
/// </summary>
/// <param name="strDbPath">要创建的SQLite数据库文件路径</param>
/// <param name="strdbTableCreateString">要创建的SQLite数据库表格</param>
public static void CreateDB(string strDbPath, string strdbTableCreateString)
{
using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + strDbPath))
{
connection.Open();
using (SQLiteCommand command = new SQLiteCommand(connection))
{
command.CommandText = strdbTableCreateString;
command.ExecuteNonQuery();
}
}
}
/// <summary>
/// 对SQLite数据库执行增删改操作,返回受影响的行数。
/// </summary>
/// <param name="strSql">要执行的增删改的SQL语句</param>
/// <param name="parameters">执行增删改语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param>
/// <returns>返回受影响的行数</returns>
public int ExecuteNonQuery(string strSql, SQLiteParameter[] parameters, bool IsDelete = false)
{
try
{
int intAffectedRows = 0;
using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
{
connection.Open();
using (DbTransaction transaction = connection.BeginTransaction())
{
using (SQLiteCommand command = new SQLiteCommand(connection))
{
command.CommandText = strSql;
if (parameters != null)
{
command.Parameters.AddRange(parameters);
}
intAffectedRows = command.ExecuteNonQuery();
}
transaction.Commit();
if (IsDelete)
{
//sqlite 真空命令,文件压缩:VACUUM 命令通过复制主数据库中的内容到一个临时数据库文件,然后清空主数据库,并从副本中重新载入原始的数据库文件。
//这消除了空闲页,把表中的数据排列为连续的,另外会清理数据库文件结构。
using (SQLiteCommand command = new SQLiteCommand(connection))
{
command.CommandText = "VACUUM";
command.ExecuteNonQuery();
}
}
}
}
return intAffectedRows;
}
catch(Exception ex)
{
Console.WriteLine("执行sql语句异常," +ex.Message + "\r\n详细sql语句为:" + strSql);
return -1;
}
}
public int ExecuteNonQueryByDic(string strSql, Dictionary<string, object> dicParams)
{
try
{
int intAffectedRows = 0;
using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
{
connection.Open();
using (DbTransaction transaction = connection.BeginTransaction())
{
using (SQLiteCommand command = new SQLiteCommand(connection))
{
command.CommandText = strSql;
if (dicParams != null && dicParams.Count > 0)
{
command.Parameters.Clear();
foreach (string parameterName in dicParams.Keys)
{
command.Parameters.AddWithValue(parameterName, dicParams[parameterName]);
}
}
intAffectedRows = command.ExecuteNonQuery();
}
transaction.Commit();
}
}
return intAffectedRows;
}
catch(Exception ex)
{
Console.WriteLine("执行sql语句异常," + ex.Message + "\r\n详细sql语句为:" + strSql);
return -1;
}
}
/// <summary>
/// 执行一个查询语句,返回一个关联的SQLiteDataReader实例
/// </summary>
/// <param name="strSql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param>
/// <returns>返回SQLiteDataReader</returns>
public SQLiteDataReader ExecuteReader(string strSql, SQLiteParameter[] parameters)
{
SQLiteConnection connection = new SQLiteConnection(m_strConnectString);
SQLiteCommand command = new SQLiteCommand(strSql, connection);
if (parameters != null)
{
command.Parameters.AddRange(parameters);
}
connection.Open();
return command.ExecuteReader(CommandBehavior.CloseConnection);
}
/// <summary>
/// 执行一个查询语句,返回一个包含查询结果的DataTable
/// </summary>
/// <param name="strSql">要执行的查询语句</param>
/// <param name="parameters">执行SQL查询语句所需要的参数,参数必须以它们在SQL语句中的顺序为准</param>
/// <returns>返回数据表</returns>
public DataTable ExecuteDataTable(string strSql, SQLiteParameter[] parameters)
{
using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
{
using (SQLiteCommand command = new SQLiteCommand(strSql, connection))
{
if (parameters != null)
{
command.Parameters.AddRange(parameters);
}
SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
DataTable data = new DataTable();
adapter.Fill(data);
return data;
}
}
}
public DataTable GetDataTable(string strSql, Dictionary<string, object> dicParams)
{
using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
{
using (SQLiteCommand command = new SQLiteCommand(strSql, connection))
{
if (dicParams != null && dicParams.Count > 0)
{
command.Parameters.Clear();
foreach (string parameterName in dicParams.Keys)
{
command.Parameters.AddWithValue(parameterName, dicParams[parameterName]);
}
}
SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
DataTable data = new DataTable();
adapter.Fill(data);
return data;
}
}
}
public DataSet ExcuteDataSet(string strSql)
{
DataSet ds = new DataSet("MyDataSet");
using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
{
using (SQLiteCommand command = new SQLiteCommand(strSql, connection))
{
SQLiteDataAdapter adapter = new SQLiteDataAdapter(command);
adapter.Fill(ds);
return ds;
}
}
}
/// <summary>
/// 执行一个查询语句,返回查询结果的第一行第一列
/// </summary>
/// <param name="strSql">要执行的查询语句</param>
/// <returns>返回第一行第一列的值</returns>
public object ExecuteScalar(string strSql)
{
try
{
using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
{
connection.Open();
using (SQLiteCommand command = new SQLiteCommand(strSql, connection))
{
return command.ExecuteScalar();
}
}
}
catch
{
throw;
}
}
public int ExecuteScalarInt(string strSql)
{
object oRes = ExecuteScalar(strSql);
return oRes == null ? 0 : Convert.ToInt32(oRes);
}
/// <summary>
/// 查询数据库中的所有数据类型信息
/// </summary>
/// <returns>返回数据表</returns>
public DataTable GetSchema()
{
using (SQLiteConnection connection = new SQLiteConnection(m_strConnectString))
{
connection.Open();
DataTable data = connection.GetSchema("TABLES");
connection.Close();
return data;
}
}
}
}