簡體   English   中英

如何提高 C# 中的 sqlite 寫入性能

[英]How to improve sqlite write performance in C#

我正在使用 sqlite 來保存日志並滿足寫入性能問題。

string log = "INSERT INTO Log VALUES ('2019-12-12 13:43:06','Error','Client','This is log message')"

public int WriteLog(string log)
{
    return ExecuteNoQuery(log);
}
public int ExecuteNoQuery(string command)
{
    int nResult = -1;
    try
    {
        using (SQLiteConnection dbConnection = new SQLiteConnection(ConnectString))
        {
            dbConnection.Open();
            using (SQLiteCommand dbCommand = dbConnection.CreateCommand())
            {
                dbCommand.CommandText = command;
                nResult = dbCommand.ExecuteNonQuery();
            }
        }
    }
    catch (Exception e)
    {
        // Output error message
    }
    return nResult;
}

在google中搜索,transaction可以顯着提高寫入性能,但不幸的是我不知道什么時候會出現日志消息,我無法合並日志消息。 還有其他方法可以提高我的日志寫入性能嗎?

我試圖在我的代碼中添加一個計時器並自動提交事務。 但我認為這不是加快日志寫入性能的好方法。

public class DatabaseManager : IDisposable
{
    private static SQLiteTransaction transaction = null;
    private SQLiteConnection dbConnection = null;
    private static Timer transactionTimer;
    private long checkInterval = 500;

    private DatabaseManager(string connectionString)
    {
        dbConnection = new SQLiteConnection(connectionString);
        dbConnection.Open();
        StartTransactionTimer();
    }

    public void Dispose()
    {
        if(transaction != null)
        {
            transaction.Commit();
            transaction = null;
        }
        dbConnection.Close();
        dbConnection =  null;
    }

    private void StartTransactionTimer()
    {
        transactionTimer = new Timer();
        transactionTimer.Interval = checkInterval;
        transactionTimer.Elapsed += TransactionTimer_Elapsed;
        transactionTimer.AutoReset = false;
        transactionTimer.Start();
    }

    private void TransactionTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        StartTransation();
        transactionTimer.Enabled = true;
    }

    public void StartTransation()
    {
        try
        {
            if (dbConnection == null || dbConnection.State == ConnectionState.Closed)
            {
                return;
            }
            if (transaction != null)
            {
                transaction.Commit();
                transaction = null;
            }
            transaction = dbConnection.BeginTransaction();
        }
        catch(Exception e)
        {
            LogError("Error occurs during commit transaction, error message: " + e.Message);
        }
    }

    public int ExecuteNoQuery(string command)
    {
        int nResult = -1;
        try
        {
            using (SQLiteCommand dbCommand = dbConnection.CreateCommand())
            {
                dbCommand.CommandText = command;
                nResult = dbCommand.ExecuteNonQuery();
            }
        }
        catch (Exception e)
        {                
            LogError("Error occurs during execute sql no result query, error message: ", e.Message);
        }
        return nResult;
    }
}

這最初是作為評論,但它正在演變為答案。

  1. 擺脫GC.Collect(); 代碼行。
    處理垃圾收集不是您的工作 - 您可能會因為使用它而降低性能。
  2. 無需關閉連接,反正你是在下一行處理它。
  3. 你為什么要鎖? 插入語句通常是線程安全的——這似乎不是該規則的例外。
  4. 你正在吞咽異常。 這是一個可怕的習慣。
  5. 由於您只插入一條記錄,因此不需要返回 int - 您只需返回一個 bool (成功為true ,失敗為false

為什么不使用實體框架與數據庫進行通信? 對我來說是最簡單的方法。 它是一個 Microsoft 庫,因此您可以確保性能非常好。 我用實體框架和 sqlite db 做了一些工作,一切都很好。 這里有一個使用示例:

var context = new MySqliteDatabase(new SQLiteConnection(@"DataSource=D:\\Mydb.db;cache=shared"));
var author = new Author {
    FirstName = "William",
    LastName = "Shakespeare",
    Books = new List<Book>
    {
        new Book { Title = "Hamlet"},
        new Book { Title = "Othello" },
        new Book { Title = "MacBeth" }
    }
};
context.Add(author);
context.SaveChanges();

MySqliteDatabase的類型可以使用數據庫優先方法或代碼優先方法自動創建。 你在互聯網上有很多信息和例子。 這里是官方文檔的鏈接: https : //docs.microsoft.com/en-us/ef/ef6/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM