ADO.NET 2.0 DataRowのインデクサ呼び出しのアクセススピード
DataRowの各要素にアクセスするには、以下の3通りの方法がある。
1.インデクサに整数を指定する
Int32 n = (Int32)row[0];
2.インデクサに文字列を指定する
Int32 n = (Int32)row["id"];
3.インデクサにDataColumn型を指定する
DataColumn idCol = new DataColumn("id", typeof(Int32)); Int32 n = (Int32)row[idCol];
結論から言うと、この3通りの中の「3.インデクサにDataColumnを指定する」が一番速い。
計測用コードは以下の通り。OdbcDataAdapterのFillでDataTableにレコードを取得し、DataRowのインデクサを実行しているだけのコードです。データベースはPostgreSQLを用いて、DataAdapterのFillで取得したレコード数は3行です。
テーブルは以下のSQLで作成し、データを入れておく。
CREATE TABLE users(id int4, name text); INSERT INTO users(id, name) VALUES(0, 'name0'); INSERT INTO users(id, name) VALUES(1, 'name1'); INSERT INTO users(id, name) VALUES(2, 'name2');
using System; using System.Collections.Generic; using System.Linq; using System.Data; using System.Data.Odbc; using System.Diagnostics; class Program { static void Main(string[] args) { String connStr = "接続文字列"; OdbcConnection conn = new OdbcConnection(connStr); OdbcDataAdapter da = new OdbcDataAdapter(connStr, conn); DataTable table = new DataTable(); da.SelectCommand = new OdbcCommand("SELECT id, name FROM users;", conn); da.Fill(table); const Int32 count = 5000000; Stopwatch sw; //-------------------------------------------- //1.DataRowのインデクサに整数を指定する sw = Stopwatch.StartNew(); for (Int32 i = 0; i < count; i++) { foreach (DataRow row in table.Rows) { Int32 id = (Int32)row[0]; String name = (String)row[1]; } } Console.WriteLine("Case1(Integer) Elapsed:{0}", sw.Elapsed); //-------------------------------------------- //2.DataRowのインデクサに文字列を指定する sw = Stopwatch.StartNew(); for (Int32 i = 0; i < count; i++) { foreach (DataRow row in table.Rows) { Int32 id = (Int32)row["id"]; String name = (String)row["name"]; } } Console.WriteLine("Case2(String) Elapsed:{0}", sw.Elapsed); //-------------------------------------------- //3.DataRowのインデクサにDataColumnを指定する sw = Stopwatch.StartNew(); DataColumn idCol = table.Columns[0]; DataColumn nameCol = table.Columns[1]; for (Int32 i = 0; i < count; i++) { foreach (DataRow row in table.Rows) { Int32 id = (Int32)row[idCol]; String name = (String)row[nameCol]; } } Console.WriteLine("Case3(DataColumn) Elapsed:{0}", sw.Elapsed); } }
結果
Case1(Integer) Elapsed:00:00:01.9515062 Case2(String) Elapsed:00:00:03.9037814 <span style="color:#FF0000;">Case3(DataColumn) Elapsed:00:00:01.7584871</span>
所要時間は、「DataColumn < Integer < String」となり、DataColumnが一番速い。また、インデクサに文字列を指定するよりもDataColumnを指定した方が2倍以上高速。DataRowに頻繁にアクセスするようなプログラムは、文字列でインデクサにアクセスせずにDataColumnにすると高速化が期待できる。
参考
プログラミングADO.NET2.0 (日経BPソフトプレス David Sceppa著)