2015-11-09 41 views
2

我有下面的代碼在C#WPF加載數據的時間很長。大數據量。在C#中的SQL查詢

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

這裏的問題是所有對數據庫的請求都需要耗費大量的時間才能完成。我看到循環運行良好,但肯定沒有優化。

那麼,我該如何提高這個過程的速度呢?

+0

對於初學者,您可以使用'where id in(1,3,5,7,8,9)',您是否真的需要選擇全部100k?如果你的數據庫中有這些ID - 你可以進行一個更快的連接。 –

+0

@ juergen-d數據庫有成對的id,CP。我需要知道列表中每個元素的CP以進行統計計算。 –

+2

代碼中的ID來自哪裏?如果來自DB,那麼你可以直接加載CP –

回答

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有大約10萬項目爲好,這將需要兆RAM

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. 如果數據訪問仍然是一個瓶頸,並且您經常爲同一對象調用它,請考慮使用緩存 - 它將允許您更快地訪問數據。根據您的體系結構,內存緩存可以使數據訪問速度非常快。

  4. 這是非常具體案件,但如果CP不是唯一的(閱讀:它常常同爲多條記錄),你不妨使用GROUP查詢

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

    這樣你獲得CP值與這應該減少數據量計數

  5. 請閱讀有關SQL Injection讓你的代碼更安全

+0

我認爲我要緩存表到字典中作爲@ dmitry-bychenko建議,謝謝你的偉大回答! –

+0

@FernandoGallegoFernández謝謝你,我很高興能幫上忙。另外,請隨時接受我的回答:) – tchrikch

2

而不是逐個獲取CP,請執行一個查詢,它選擇整個表,然後在表中迭代。這將大大提高速度。 您的查詢將是:

"SELECT * FROM CP"; 

然後做這樣的事情:

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

從一個人的意見誰發揮了不少與Access的DB - 始終使用參數化查詢。它將爲您節省大部分不兼容的類型錯誤。尤其是當你使用日期...

1

修改:

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

因此,這將通過所有的ID作爲逗號分隔,給函數,它將只執行一次SQL查詢,因此數據庫連接將僅打開一次。邏輯的其餘部分應插入到存儲過程中,因爲SP再次比正常的SQL查詢快得多。 90%的時間將被保存。希望這可以工作。

相關問題