加载数据的时间很长。大量数据。 SQL C# 查询

A very long time of loading data. Large Amount of Data. SQL queries in C#

我在 C# WPF 中有以下代码

ConsultaDB consulta = new ConsultaDB();
foreach (var item in lista)
{
    var cp = consulta.returnCP(item.Key);
    if (cp.Length != 5)
    {
        //Some code here with the data returned
    }
}

list 是 >100K 元素的集合,ConsultaDB 对象有以下代码:

class ConsultaDB
{
    string CP;
    OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=CCPP.accdb");
    public string returnCP(string id)
    {
        var comm = conn.CreateCommand();
        comm.CommandType = CommandType.Text;
        comm.CommandText = "SELECT CP FROM CP WHERE ID='" + id+ "'";
        var returnValue = comm.ExecuteScalar();
        CP = returnValue.ToString();
        return CP;
    }

    public ConsultaDB()
    {
        conn.Open();
    }
}

这里的问题是所有对数据库的请求都需要花费大量时间才能完成。我看到循环运行良好,但肯定没有优化。

那么,我怎样才能提高该过程的速度?

  1. 一次获取更多数据 - 因为您提前知道 ID 列表,而不是通过调用一个一个地查询项目。如果您想要带有键 (1,2,3,4) 的项目,那么只需执行一个

    而不是执行 4 个查询
    SELECT CP FROM CP WHERE ID IN (1,2,3,4)
    

    C# 代码中这意味着

    public string returnCP(List<string> ids)
        {
            var comm = conn.CreateCommand();
            comm.CommandType = CommandType.Text;
            comm.CommandText = string.Format( "SELECT CP FROM CP WHERE ID IN({0})",string.Join(",",ids));
            var returnValue = comm.ExecuteScalar();
            CP = returnValue.ToString();
            return CP;
        }
    
  2. 页面请求,如果你需要很多id。如果您需要 10,000 个 ID,一次加载所有 ID 的效率会很低——最好将数据请求分成几个小块。这样他们仍然可以加载几百条记录,但不会太多。

  3. 如果数据访问仍然是一个瓶颈,并且您经常为相同的对象调用它,请考虑使用 缓存 - 它可以让您更快地访问数据。根据您的架构,内存缓存可以使数据访问速度极快。

  4. 这是非常具体的案例,但如果 CP 不是唯一的(阅读:许多记录通常是相同的)你也可以使用 GROUP 查询

    SELECT CP,COUNT(*) FROM CP GROUP BY CP
    

    通过这种方式,您可以获得 CP 个具有计数的值,应该减少数据量

  5. 请阅读 SQL Injection 以使您的代码更安全

不是一个一个地获取 CP,而是执行单个查询,选择整个 table,然后在 table 中迭代。会大大提高速度。 您的查询将是:

"SELECT * FROM CP";

然后做类似的事情:

 List<string> cps = table_name.AsEnumerable()
                           .Select(r=> r.Field<string>("...."))
                           .ToList();

一个经常使用 Access DB 的人的建议 - 始终使用参数化查询。它将为您避免大部分不兼容的类型错误。特别是当你处理日期时...

您可以尝试将整个 CP table 缓存在字典中:

class ConsultaDB {
  private static Dictionary<String, String> s_Data = new
    Dictionary<String, String>();

  private static void CoreFeedCache() {
    using (OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=CCPP.accdb")) {
      using (var comm = conn.CreateCommand()) {
        comm.CommandText = 
          @"select ID,
                   CP
              from CP";

        using (reader = comm.ExecuteReader()) {
          while (reader.Read()) {
            s_Data.Add(Convert.ToString(reader[0]), Convert.ToString(reader[1]));
          }  
        }
      }
    }
  } 

  static {
    CoreFeedCache();
  }

  public static string returnCP(string id) {
    String result;

    if (!s_Data.TryGetValue(id, out result))
      result = null;

    return result;
  } 
}

如果 CP 也有大约 100K 个项目,它将需要 MegaBytes 的 RAM。

修改:

var strId=string.empty;
lista.Foreach(x=>
{
strId+=","+x.itemKey;
});
var cp = consulta.returnCP(strId=strId.TrimStart(','));

所以这会将所有 id 作为逗号分隔传递给函数,它只会执行一次 SQL 查询,因此数据库连接只会打开一次。其余的逻辑应该插入存储过程中,因为 SP 再次比普通 SQL 查询快得多。将节省 90% 的时间。希望这有效。