2011-09-16 40 views
1

第三方應用程序爲每個項目創建一個數據庫。所有的數據庫都有相同的表和結構。新項目可能隨時添加,因此我無法使用任何EF模式。優化對未知數據庫的查詢

我現在要做的是:

private IEnumerable<Respondent> getListRespondentWithStatuts(string db) 
    { 
     return query("select * from " + db + ".dbo.respondent"); 
    } 

    private List<Respondent> query(string sqlQuery) 
    { 
     using (var sqlConx = new SqlConnection(Settings.Default.ConnectionString)) 
     { 
      sqlConx.Open(); 
      var cmd = new SqlCommand(sqlQuery, sqlConx); 
      return transformReaderIntoRespondentList(cmd.ExecuteReader()); 
     } 
    } 

    private List<Respondent> transformReaderIntoRespondentList(SqlDataReader sqlDataReader) 
    { 
     var listeDesRépondants = new List<Respondent>(); 

     while (sqlDataReader.Read()) 
     { 
      var respondent = new Respondent 
      { 
       CodeRépondant = (string)sqlDataReader["ResRespondent"], 
       IsActive = (bool?)sqlDataReader["ResActive"], 
       CodeRésultat = (string)sqlDataReader["ResCodeResult"], 
       Téléphone = (string)sqlDataReader["Resphone"], 
       IsUnContactFinal = (bool?)sqlDataReader["ResCompleted"] 
      }; 

      listeDesRépondants.Add(respondent); 
     } 

     return listeDesRépondants; 
    } 

這工作得很好,但它是致命的緩慢(20個000記錄每分鐘)。你有什麼提示什麼策略應該更快?對於信息,什麼是真的很慢transformReaderIntoRespondentList方法

謝謝!

+3

你做一個select *,只查詢你需要的字段 – Peter

+0

是的,試過了,5分鐘就獲得了5秒。這就是我認爲緩慢來自轉型的原因。但好點 – Mathieu

+1

爲什麼你嵌入SQL而不是編寫一個存儲過程來調用參數? – Wil

回答

2

一般來說,任何東西SELECT * FROM是不好的做法,但它也可能導致你不得不拉回比實際需要更多的數據。該轉換僅在少數列上運行,而列數多於要求返回的列數?考慮更換:

private IEnumerable<Respondent> getListRespondentWithStatuts(string db) 
    { 
    return query("select ResRespondent, ResActive, ResCodeResult, Resphone, ResCompleted from " + db + ".dbo.respondent"); 
    } 

此外,針對SQL注入攻擊gaurd;級聯字符串用於SQL查詢是非常危險的。

當從DataReader提取數據,我發現使用非命名查找最好:

var respondent = new Respondent 
    { 
    CodeRépondant = sqlDataReader.GetString(0), 
    IsActive = sqlDataReader.IsDBNull(1) ? (Boolean?)null : sqlDataReader.GetBoolean(1), 
    CodeRésultat = sqlDataReader.GetString(2), 
    Téléphone = sqlDataReader.GetString(3), 
    IsUnContactFinal = sqlDataReader.IsDBNull(4) ? (Boolean?)null : sqlDataReader.GetBoolean(4) 
    }; 

我沒有explcicitly測試了很長一段時間的性能差異;但那曾經有一個顯着的區別。序號檢查不必進行命名查找,也避免了裝箱/取消裝箱值。

除此之外,沒有更多的信息,很難說......你需要所有20,000條記錄嗎?

UPDATE

然簡單本地測試用例300000個記錄和減少了近50%加載所有數據的時間。我想這些結果會因所檢索數據的類型而異。但它對整體執行時間仍然有影響。這就是說,在我的環境中,我們正在談論從650毫秒降至300毫秒以上。

注意

如果respondent一種說法,什麼是可能的「非常慢」是數據庫建立的結果集;儘管只要記錄可用,數據讀取器就會開始處理信息,但最終的瓶頸將是數據庫本身和/或網絡延遲。除了上述優化之外,除非您可以對視圖/表進行索引以優化查詢和/或減少所需的信息,否則用代碼可以做的事情不會太多。

+0

我馬上試試。我需要所有這些記錄,主要是因爲我需要使用ResRespondent作爲參數調用存儲過程。我還沒有找到任何關於這個過程的捷徑。 – Mathieu

+0

結果相差40%。這很不錯!感謝您的建議! – Mathieu