2016-06-10 34 views
0

上下文:我檢索大量數據以在ElasticSearch集羣中對其進行索引(它具有no-sql格式)。c#更好的方式來從SQL Server 2014中檢索大量數據?

我這樣做是通過確定有多少代表需要使用for循環創建,具體取決於當前分析表與我的bulk_size相比有多少行,並執行它們以執行下面的代碼。我使用offset-fetchtb表示當前的表,我目前bulk_size是5000

我的代碼如下所示:

using (SqlConnection db = new SqlConnection(tb.Conn)) 
{ 
    int offset = i * BULK_SIZE; 
    int nextRows = BULK_SIZE; 

    string queryParams = string.Format(" ORDER BY {0} OFFSET {1} ROWS FETCH NEXT {2} ROWS ONLY", tb.FirstPK(), offset, nextRows); 

    string dataQuery = string.Format("SELECT * FROM dbo.{0} {1}", tb.TableName, queryParams); 

    try 
    { 
     db.Open(); 
     object[,] bulk = new object[BULK_SIZE, 2];//[data[], id] 
     int n = 0; 
     object[] values; 

     using (SqlDataReader reader = new SqlCommand(dataQuery, db).ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       string docId = string.Empty; 

       foreach (string pk in tb.PKeys) 
       { 
        docId += reader[pk].ToString() + '_'; 
       } 

       docId = docId.Substring(0, docId.Length - 1);//delete last '_' 
       values = new object[reader.FieldCount]; 

       reader.GetValues(values); 

       bulk[n, 0] = values; 
       bulk[n, 1] = docId; 

       n++; 
      } 

      reader.Close(); 
     } 

     db.Close(); 

     if (IsMemoryAvailable())//Waits for other delegates to finish 
     { 
      DataUpload(bulk, tb, mapper); 
     } 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); Console.ReadLine(); 
     //throw e; 
    } 
} 

有沒有更好的方式來做到這一點?

我得到然後批量,插入到一個數組並處理在另一個任務批量。

問題是SQL Server的內存不斷增大(緩存變得太大),並且在後期大容量獲取中,我得到超時異常等;它會變慢。

+0

我會建議改變你的'SELECT * FROM'選擇你需要的實際列..如果你需要2列然後不使用select *也改變這個查詢是一個存儲過程 – MethodMan

+0

什麼是在那裏有Task.Run?恕我直言,它只是浪費一個額外的線程,因爲調用線程仍然被Wait()阻塞。另外,如果那裏的代碼會拋出異常,你將會得到AggregateException而沒有任何有意義的消息。 –

+0

@KasparsOzols你是對的;我在「Task.WaitAll」調用中封裝任務時遇到了問題,但以後忘記更改它。 –

回答

0

解決方法是創建一個只有主鍵的臨時表,並從表和帶有連接的臨時表中來回查詢。

這是比offset-fetch更高的內存效率,也更快。

相關問題