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;
            }
        }
    }
}
相关推荐
Wang's Blog1 小时前
Redis: 集群环境搭建,集群状态检查,分析主从日志,查看集群信息
数据库·redis
容器( ु⁎ᴗ_ᴗ⁎)ु.。oO1 小时前
MySQL事务
数据库·mysql
cyt涛3 小时前
MyBatis 学习总结
数据库·sql·学习·mysql·mybatis·jdbc·lombok
Rookie也要加油3 小时前
01_SQLite
数据库·sqlite
liuxin334455663 小时前
教育技术革新:SpringBoot在线教育系统开发
数据库·spring boot·后端
看山还是山,看水还是。4 小时前
MySQL 管理
数据库·笔记·mysql·adb
fishmemory7sec4 小时前
Koa2项目实战2(路由管理、项目结构优化)
数据库·mongodb·koa
momo小菜pa4 小时前
【MySQL 09】表的内外连接
数据库·mysql
Jasonakeke5 小时前
【重学 MySQL】四十九、阿里 MySQL 命名规范及 MySQL8 DDL 的原子化
数据库·mysql
程序猿小D5 小时前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa