2011-09-16 9 views
1

サードパーティのアプリケーションは、プロジェクトごとに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

300,000レコードを持つ単純なローカルテストケースを実行し、ほぼ50%のすべてのデータをロードする時間を減少させました。私はこれらの結果が検索されているデータの種類によって異なることを想像しています。それでも全体的な実行時間に違いはあります。私の環境では、650msから300msを少し下回っていると言われています。

NOTE

respondentが表示された場合、どのような「本当に遅い」と思われることは、結果セットを構築するデータベースです。レコードが利用可能になるとすぐにデータリーダーで情報の処理が開始されますが、最終的なボトルネックはデータベース自体および/またはネットワークの待ち時間になります。上記の最適化以外にも、ビュー/テーブルのインデックスを作成してクエリを最適化したり、必要な情報を減らしたりしない限り、コードで行うことはあまりありません。

+0

すぐにこれを試してみます。そして、私はこれらのレコードをすべて必要とするのは、ResRespondentをパラメータとしてストアプロシージャを呼び出す必要があるからです。私はそのプロセスへのショートカットを発見していない。 – Mathieu

+0

結果は40%の差です。それはかなり良いです!助けてくれてありがとう! – Mathieu