【问题标题】:What is the fastest way to read the SQL Data (Millions of records) from database SQLite C# Service Stack从数据库 SQLite C# 服务堆栈中读取 SQL 数据(数百万条记录)的最快方法是什么
【发布时间】:2015-05-05 14:57:06
【问题描述】:

我正在使用 SQLite 作为数据库来开发 Ormlite-ServiceStack。 我在单个 Select 查询(C# DotNet 和数据库是 SQLite (v4.0.30319))中从 SQLite 数据库表中检索数百万 (1195935) 条记录,如下所示。

SQLite 不支持存储过程。

单个查询检索数据的整个过程需要 30 多秒。如何提高毫秒级别的性能。我尝试过其他方式,如 Entity Framework、SQLiteData Adapter,但无法提高从数据库中获取数据的毫秒级速度。

我的机器也是速度非常快的固态硬盘,配备 16 GB RAM,基于 X64 的 Windows 7 专业版。


public string connectionstring** = "Data Source =  " + System.Configuration.ConfigurationManager.AppSettings["DatabasePath"].ToString() + ";";

public class ClientSideDataResponse
{
    public int ID { get; set; }
    public int ByDevSessionId { get; set; }
    public int ByDeviceId { get; set; }
    public int value1 { get; set; }
    public int value2 { get; set; }
    public int  SequenceId{ get; set; }
    public DateTime Timestamp { get; set; }
}

    public List< ClientSideDataResponse> executeReadQuery_List_ClientSideData() 
    {
        System.Data.SQLite.SQLiteCommand myCommand = new System.Data.SQLite.SQLiteCommand();
        List<ClientSideDataResponse> results = new List<ClientSideDataResponse>();

        String _query = "SELECT ID, ByDevSessionId, ByDeviceId, Value1, Value2,  SequenceId, Timestamp   FROM ClientSideData ORDER BY ID";

        try
        {
            using (System.Data.SQLite.SQLiteConnection con = new System.Data.SQLite.SQLiteConnection(connectionstring))
            {
                using (var cmd = con.CreateCommand())
                {
                    if (con.State == ConnectionState.Closed || con.State == ConnectionState.Broken)
                    {
                        con.Open();
                    }

                    using (var transaction = con.BeginTransaction())
                    {
                        cmd.CommandText = _query;
                        try
                        {
                            System.Data.SQLite.SQLiteDataReader reader = cmd.ExecuteReader();
                            while (reader.Read())
                            {
                                 ClientSideDataResponse  newItem = new ClientSideDataResponse();

                                if (!string.IsNullOrEmpty(reader["ID"].ToString()) == true)
                                {
                                    newItem.ID = Convert.ToInt32(reader["ID"]);
                                }
                                if (!string.IsNullOrEmpty(reader["ByDevSessionId"].ToString()) == true)
                                {
                                    newItem.ByDevSessionId = Convert.ToInt32(reader["ByDevSessionId"]);
                                }
                                if (!string.IsNullOrEmpty(reader["ByDeviceId"].ToString()) == true)
                                {
                                    newItem.ByDeviceId = Convert.ToInt32(reader["ByDeviceId"]);
                                }  
                                if (!string.IsNullOrEmpty(reader["Value1"].ToString()) == true)
                                {
                                    newItem.Value1 = Convert.ToInt32(reader["Value1"]);
                                }
                                if (!string.IsNullOrEmpty(reader["Value2"].ToString()) == true)
                                {
                                    newItem.Pulse = Convert.ToInt32(reader["Value2"]);
                                }
                                if (!string.IsNullOrEmpty(reader["SequenceId"].ToString()) == true)
                                {
                                    newItem.SequenceId = Convert.ToInt32(reader["SequenceId"]);
                                }
                                if (!string.IsNullOrEmpty(reader["Timestamp"].ToString()) == true)
                                {
                                    newItem.Timestamp = Convert.ToDateTime(reader["Timestamp"].ToString());
                                }

                                results.Add(newItem);
                            }
                            reader.Close();
                        }
                        catch (Exception ex)
                        { 
                            logger.Debug(ex.Message);
                            return results;
                        }

                        transaction.Commit();
                        cmd.Dispose();

                        if (con.State == ConnectionState.Open)
                        {
                            con.Close();
                        }
                        return results;
                    }
                }
            }
        }
        catch (Exception ex)
        {
             logger.Debug(ex.Message);
            return results;
        }
    }

【问题讨论】:

  • 您将结果用于什么目的?您真的需要检索所有数据吗?
  • 每秒 40K 记录听起来还不错...您的性能目标是什么?
  • 在 30 秒内从平面文件关系数据库中获取 120 万条记录一点也不差,尤其是使用 Order By。如果您需要更快的东西,请将您的数据库扩展到 SqlServer 或 MySql 之类的东西。
  • 根据之前的评论,您尝试执行的操作使用了错误的数据库后端。
  • 但是你真的需要数百万行数据来绘制折线图吗?

标签: c# asp.net sql-server sqlite ormlite-servicestack


【解决方案1】:

您可以采取一些措施来加快速度。 (但它可能不会让它更快)

  1. 如果需要,请创建索引以提高order by 的性能。查看查询的执行计划。或者更好的是,如果消费者不需要,请删除order by
  2. 将结果列表的容量设置为与已知结果相近的值。 new List&lt;ClientSideDataResponse&gt;(1200000);
  3. 不要与string 相互转换,而是使用数据库中的实际值。 (当然除非数据库中的值实际上是字符串,那么就需要重新设计)

这个:

if (!string.IsNullOrEmpty(reader["ID"].ToString()) == true)
{
     newItem.ID = Convert.ToInt32(reader["ID"]);
}

改为:

if(!reader.IsDBNull(0)) //0 is the index of the column.
   newItem.ID = reader.GetInt32(0); 

查询的所有其他结果也是如此。

【讨论】:

    【解决方案2】:

    ServiceStack 具有为您完成所有这些工作的选择方法。

    Chek ServiceStack.OrmLite 项目。它也处理 SQLite 数据库。

    你只需要调用类似的东西:

    var results = Db.Select<ClientSideDataResponse>(); // That's all folks!
    

    【讨论】:

      【解决方案3】:

      我很惊讶没有人告诉您不要从单个查询中检索数百万条记录。特别是因为它被标记为asp.net(网络)。只需拉出总计数和当前页面所需的记录。现在确定您的页面大小并创建您的自定义分页,当用户单击页面“n”时检索第 n 个页面。对于第 n 页,算法将是

       records.Skip( (n-1) * page_size ).Take( page_size )
      

      如果您使用的是 EntityFramework。

      【讨论】:

      • 这是对该问题的第一条评论。
      猜你喜欢
      • 2011-04-26
      • 2019-07-12
      • 2012-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多