2011-11-06 9 views
7

SQLサーバーからできるだけ早くデータを読み取る方法を試しています。興味深い発見が出ました。 List<string[]>の代わりにList<object[]>にデータを読み取ると、パフォーマンスが2倍以上向上します。SqlDataReaderパフォーマンスリスト<string[]>またはリスト<object[]>

これはフィールド上でToString()メソッドを呼び出す必要がないと思われますが、オブジェクトを使用するとパフォーマンスに悪影響が及ぶと常に考えていました。

文字列配列の代わりにオブジェクト配列のリストを使用しない理由はありますか?

EDIT:このデータの保存容量は私が持っていたものの1つです。オブジェクト配列にデータを格納するのは文字列よりも余裕がありますか?

private void executeSqlObject() 
    { 
     List<object[]> list = new List<object[]>(); 

     using (SqlConnection cnn = new SqlConnection(_cnnString)) 
     { 
      cnn.Open(); 
      SqlCommand cmd = new SqlCommand("select * from test_table", cnn); 

      SqlDataReader reader = cmd.ExecuteReader(); 

      int fieldCount = reader.FieldCount; 

      while (reader.Read()) 
      { 
       object[] row = new object[fieldCount]; 

       for (int i = 0; i < fieldCount; i++) 
       { 
        row[i] = reader[i]; 
       } 
       list.Add(row); 
      } 
     } 
    } 

    private void executeSqlString() 
    { 
     List<string[]> list = new List<string[]>(); 

     using (SqlConnection cnn = new SqlConnection(_cnnString)) 
     { 
      cnn.Open(); 
      SqlCommand cmd = new SqlCommand("select * from test_table", cnn); 

      SqlDataReader reader = cmd.ExecuteReader(); 

      int fieldCount = reader.FieldCount; 

      while (reader.Read()) 
      { 
       string[] row = new string[fieldCount]; 

       for (int i = 0; i < fieldCount; i++) 
       { 
        row[i] = reader[i].ToString(); 
       } 
       list.Add(row); 
      } 
     } 
    } 

    private void runTests() 
    { 
     Stopwatch watch = new Stopwatch(); 
     for (int i = 0; i < 10; i++) 
     { 
      watch.Start(); 
      executeSqlObject(); 
      Debug.WriteLine("Object Time: " + watch.ElapsedMilliseconds.ToString()); 
      watch.Reset(); 
     } 
     for (int i = 0; i < 10; i++) 
     { 
      watch.Start(); 
      executeSqlString(); 
      Debug.WriteLine("String Time: " + watch.ElapsedMilliseconds.ToString()); 
      watch.Reset(); 
     } 
    } 

と結果:あなたは追加ボクシングを起こしている場合

Object Time: 879 
Object Time: 812 
Object Time: 825 
Object Time: 882 
Object Time: 880 
Object Time: 905 
Object Time: 815 
Object Time: 799 
Object Time: 823 
Object Time: 817 
Average: 844 

String Time: 1819 
String Time: 1790 
String Time: 1787 
String Time: 1856 
String Time: 1795 
String Time: 1731 
String Time: 1792 
String Time: 1799 
String Time: 1762 
String Time: 1869 
Average: 1800 
+1

結果と主張することはできません。また、メモリをリークする可能性があるため、読者(およびコマンド)もステートメントを使用してラップする必要があります。 –

+0

テストには何か問題があります...データベースからデータを読み込むのと比較して、文字列型チェック*を間違っていなければなりません。 – Guffa

+0

好奇心を失って、ToString()を呼び出すのではなく、リーダの値を文字列( 'row [i] =(string)reader [i];')にキャストするか、組み込みの 'SqlDataReader.GetString()'メソッドを使用して値を取得します( 'row [i] = reader.GetString(i);')? (すべての列の値は文字列です) –

答えて

8

objectだけオーバーヘッド追加

は、ここに私のテストコードです。それでも、この影響はごくわずかです。あなたの場合、reader[i]常にobjectを返します。すでにobjectという文字列を持っているかどうかは関係ありません。.ToString()の呼び出しでオーバーヘッドが追加されます。ほとんどの場合(int、DateTimeなど)、これには書式設定コードの両方に1つ(またはそれ以上)余分な文字列が割り当てられます。 stringに変更すると、のデータを変更する(悪い場合は、たとえば、日付のソートを正しく行うことができなくなります)、オーバーヘッドを追加することができます。ここでの端の場合は、すべての列がすでに実際に文字列である場合です。この場合、いくつかの仮想メソッド呼び出しを追加するだけです(実際の作業は不要です)。

生の演奏の後であれば、ダッパーなどのマイクロORMを見ることをお勧めします。彼らは大きく最適化されていますが、 "フル" ORMの重さは避けてください。たとえば、dapper:

var myData = connection.Query<TypedObject>("select * from test_table").ToList(); 

のように、厳密に型指定されたオブジェクトデータを与えている間は非常に似通ったパフォーマンスを期待します。

+0

マーク、良い情報をありがとう。マイクロORMソリューションを参照すると、このソリューションではクエリを実行する前に取得するデータセットを知る必要はありませんか?このアプリケーションは、検索しているデータには無関係である必要があります。 – ChandlerPelhams

+0

@ ChandlerPelhamsは質問からはっきりしていません; pジェネリックスを使って 'T'を渡すことはできないと仮定します(ほとんどのアプリケーションでは、データがどのように見えるかを知っている)、実際には 'object []'や「lowds」のようなもっと一般的なものが、DataTableが適切かもしれません。 –

1

文字列配列の代わりにオブジェクト配列のリストを使用しない理由はありますか?

それはあなたが配列にそれらを得た後で結構ですあなたがオブジェクトのリストを持つオブジェクトとして各値の治療に満足している場合は、取得した値でやりたいことに依存する

が、もしそれらを文字列として扱いたい場合は、ある時点でオブジェクトを文字列に変換/キャストし直して、どこかでコストを負担させる必要があります。

SqlDataReaderから値を文字列として読み込んでいる場合は、値にToString()を呼び出すのではなくGetString(int)メソッドを使用してテストし、これをベンチマークとして使用する必要があります。

また、配列を使用するのではなく、その値をデータセットに読み込むことができます。これにより、後で作業するのが容易になる場合があります。

最後は、データベースから検索した結果をどのように使用するかによって決まります。

+0

笑、DataSetの有用性と配列のリスト...それは別のSO質問のための話題だと思う:) – lowds

+0

@ Marc - Me too :) – ChandlerPelhams

+0

与えられた場合、コードはレイアウトを知らないその場合、DataTableが実際に適切かもしれないことに注意する必要があります。 –

関連する問題