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;
            }
        }
    }
}
相关推荐
写bug的小屁孩几秒前
前后端交互接口(三)
运维·服务器·数据库·windows·用户界面·qt6.3
恒辉信达13 分钟前
hhdb数据库介绍(8-4)
服务器·数据库·mysql
齐 飞1 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
云空1 小时前
《Python 与 SQLite:强大的数据库组合》
数据库·python·sqlite
暮毅1 小时前
10.Node.js连接MongoDb
数据库·mongodb·node.js
wowocpp1 小时前
ubuntu 22.04 server 格式化 磁盘 为 ext4 并 自动挂载 LTS
服务器·数据库·ubuntu
成富2 小时前
文本转SQL(Text-to-SQL),场景介绍与 Spring AI 实现
数据库·人工智能·sql·spring·oracle
songqq272 小时前
SQL题:使用hive查询各类型专利top 10申请人,以及对应的专利申请数
数据库·sql
计算机学长felix2 小时前
基于SpringBoot的“校园交友网站”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·毕业设计·交友
小码的头发丝、2 小时前
Django中ListView 和 DetailView类的区别
数据库·python·django