SQLite批量操作优化方案

复制代码
using SQLiteBatch.Util;
using System.Collections.Concurrent;

namespace SQLiteBatch
{
    internal class Program
    {
        static ConcurrentQueue<string> SqlQueue = new ConcurrentQueue<string>();
        static int ExecuteCount = 10000;

        static void Main(string[] args)
        {
            // 初始化
            FreeSqlUtil.InitDB();

            // 单条执行
            Task.Run(() => TaskOne());

            // 批量添加执行
            Task.Run(() => TaskAdd());
            Task.Run(() => TaskUpdate());

            Console.ReadLine();
        }

        static async Task TaskOne()
        {
            var executeStopwatch = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < ExecuteCount; i++)
            {
                await FreeSqlUtil.UpdateChannel_One("Channel1.Device1.400101", i.ToString(), "Good", DateTime.Now.ToString()); 
            }
            executeStopwatch.Stop(); 
            Console.WriteLine($"单条执行, {ExecuteCount} 条 SQL, 总耗时: {executeStopwatch.ElapsedMilliseconds} ms");
        }

        static async Task TaskAdd()
        {
            for (int i = 0; i < ExecuteCount; i++)
            { 
                var sql = FreeSqlUtil.UpdateChannel_Much("Channel1.Device1.400101", i.ToString(), "Good", DateTime.Now.ToString());
                SqlQueue.Enqueue(sql);
            }
        }

        static async Task TaskUpdate()
        { 
            while (true)
            {
                await Task.Delay(10000);

                // 批量取出并执行SQL
                var batchSqls = new List<string>();
                while (SqlQueue.TryDequeue(out string? sql)) batchSqls.Add(sql);

                if (batchSqls.Count > 0)
                {
                    var executeStopwatch = System.Diagnostics.Stopwatch.StartNew();
                    await FreeSqlUtil.ExecuteBatchAsync(batchSqls);
                    executeStopwatch.Stop(); 
                    Console.WriteLine($"批量执行, {batchSqls.Count} 条 SQL, 总耗时: {executeStopwatch.ElapsedMilliseconds} ms");
                } 
            }
        }
    }
}
复制代码
using System.Data.Common;

namespace SQLiteBatch.Util
{
    public class FreeSqlUtil
    {
        static IFreeSql freeSql;

        public static void InitDB()
        {
            var ConnectionString = $"Data source={AppDomain.CurrentDomain.SetupInformation.ApplicationBase}{Path.DirectorySeparatorChar}Data.db";
            freeSql = new FreeSql.FreeSqlBuilder()
                        .UseConnectionString(FreeSql.DataType.Sqlite, ConnectionString)
                        .UseNoneCommandParameter(true)// 不使用参数化
                        .Build();
        }

        public static async Task<bool> UpdateChannel_One(string tag, string value, string quality, string timestamp)
        {
            bool ret = false;
            try
            {
                ret = await freeSql.Update<Channel>()
                    .Set(it => it.OPCValue == value)
                    .Set(it => it.OPCQuality == quality)
                    .Set(it => it.OPCTime == timestamp)
                    .Where(it => it.OPCTag == tag).ExecuteAffrowsAsync() > 0;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"FreeSqlHelper,UpdateChannel,errmsg:{ex.Message}\r\nstacktrace:{ex.StackTrace}");
            }
            return ret;
        }

        public static string UpdateChannel_Much(string tag, string value, string quality, string timestamp)
        {
            return freeSql.Update<Channel>()
                  .Set(it => it.OPCValue == value)
                  .Set(it => it.OPCQuality == quality)
                  .Set(it => it.OPCTime == timestamp)
                  .Where(it => it.OPCTag == tag).ToSql();
        }

        // 批量执行方法
        public static async Task ExecuteBatchAsync(List<string> lstBathSql)
        { 
            using (FreeSql.Internal.ObjectPool.Object<DbConnection> conn = freeSql.Ado.MasterPool.Get())
            {
                try
                {
                    using (DbTransaction transaction = conn.Value.BeginTransaction())
                    {
                        try
                        {
                            for (int i = 0; i< lstBathSql.Count; i++)
                            { 
                                try
                                { 
                                    await freeSql.Ado.ExecuteNonQueryAsync(transaction, lstBathSql[i]); 
                                }
                                catch (Exception ex)
                                { 
                                    Console.WriteLine($"ExecuteBatchAsync Error(1),ex:{ex.Message},sql:{lstBathSql[i]}");
                                }
                            }
                            transaction.Commit();
                        }
                        catch (Exception ex)
                        {
                            transaction.Rollback();
                            Console.WriteLine($"ExecuteBatchAsync Error(2),ex:{ex.Message}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"ExecuteBatchAsync Error(3),ex:{ex.Message}");
                }
            }
        }
    }
}
相关推荐
Flying pigs~~7 小时前
RAG智慧问答项目
数据库·人工智能·缓存·微调·知识库·rag
misL NITL7 小时前
mysql之如何获知版本
数据库·mysql
许彰午7 小时前
CacheSQL(二):主从复制——OpLog 环形缓冲区与故障自动恢复
java·数据库·缓存
2401_832365528 小时前
JavaScript中rest参数(...args)取代arguments的优势
jvm·数据库·python
2301_779622419 小时前
Go语言怎么用信号量控制并发_Go语言semaphore信号量教程【入门】
jvm·数据库·python
2301_766283449 小时前
c++如何将控制台输出保存到文件_cout重定向到txt【详解】
jvm·数据库·python
北极的冰箱9 小时前
MySQL Ver 8.0.41 for macos14.7密码遗忘
数据库·mysql
XDH_CS10 小时前
MySQL 8.0 安装与 MySQL Workbench 使用全流程(超详细教程)
开发语言·数据库·mysql
treacle田10 小时前
达梦数据库-统计信息收集-记录
数据库·达梦数据库统计信息收集
审判长烧鸡11 小时前
PostgreSQL之索引/函数/触发器
数据库·postgresql·触发器·函数·索引