Sqlite真空命令VACUUM

之前在项目中使用了sqlite数据库,当日志变大时,执行CRUD操作就会变慢

后来尝试删除7天前的记录进行优化

sql 复制代码
delete from XX_CollectData where CreateTime<='2024-01-24'

发现sqlite文件的大小就没有变化,delete命令只是逻辑删除,所在的文件的字节码仍然还在,优化效果仍不明显。

后来使用真空命令VACUUM,发现文件大小确实变小了。

sql 复制代码
VACUUM

SQLite Vacuum

VACUUM 命令通过复制主数据库中的内容到一个临时数据库文件,然后清空主数据库,并从副本中重新载入原始的数据库文件。这消除了空闲页,把表中的数据排列为连续的,另外会清理数据库文件结构。

如果表中没有明确的整型主键(INTEGER PRIMARY KEY),VACUUM 命令可能会改变表中条目的行 ID(ROWID)。VACUUM 命令只适用于主数据库,附加的数据库文件是不可能使用 VACUUM 命令。

如果有一个活动的事务,VACUUM 命令就会失败。VACUUM 命令是一个用于内存数据库的任何操作。由于 VACUUM 命令从头开始重新创建数据库文件,所以 VACUUM 也可以用于修改许多数据库特定的配置参数。

相关测试程序类【C#代码】

cs 复制代码
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;
            }
        }
    }
}
相关推荐
代码or搬砖几秒前
SQL核心语法总结:从基础操作到高级窗口函数
java·数据库·sql
7 分钟前
TIDB——TIKV——读写与coprocessor
数据库·分布式·tidb·
大猫和小黄1 小时前
若依微服务全面适配PostgreSQL-OpenGauss数据库
数据库·微服务·postgresql·若依
老徐电商数据笔记1 小时前
技术复盘第二篇:电商数据主题域划分企业级实践
大数据·数据库·数据仓库·零售·教育电商·技术面试
jfqqqqq1 小时前
postgres查询、重设自增序列的起始值
数据库·sql·postgres·自增序列
1 小时前
TIDB——PD(placement Driver)
java·数据库·分布式·tidb·
DemonAvenger1 小时前
Redis与MySQL双剑合璧:缓存更新策略与数据一致性保障
数据库·redis·性能优化
断春风2 小时前
如何避免 MySQL 死锁?——从原理到实战的系统性解决方案
数据库·mysql
闲人编程2 小时前
基础设施即代码(IaC)工具比较:Pulumi vs Terraform
java·数据库·terraform·iac·codecapsule·pulumi
QQ_21696290962 小时前
Spring Boot大学生社团管理平台 【部署教程+可完整运行源码+数据库】
java·数据库·spring boot·微信小程序