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

时间:2015-11-09 09:17:47

标签: c# sql wpf oledb

我在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();
    }
}

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

那么,我该如何提高这个过程的速度呢?

4 个答案:

答案 0 :(得分:2)

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

"SELECT * FROM CP";

然后执行以下操作:

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

一个使用Access DB玩过很多的人的建议 - 总是使用参数化查询。它将为您节省大多数不兼容的类型错误。特别是当你使用日期......

答案 1 :(得分:1)

  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,那么一次加载所有这些都是低效的 - 最好将数据请求拆分成几个小块。这样他们仍然会加载几百条记录,但不会太多。

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

  4. 这是特定于案例的,但如果CP不是唯一的(读取:对于许多记录来说,它通常是相同的),您也可以使用GROUP查询

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

    通过这种方式,您可以获得CP值,这些值可以减少数据量

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

答案 2 :(得分:1)

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

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。

答案 3 :(得分:1)

修改:

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

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