- - PR -
ハッシュテーブルの検索速度について
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2004-08-19 13:51
===>todo様
レス、ありがとうございます。 >読み込んだデータテーブルのPrimaryKeyを設定して、 .Rows.Findで検索するという手をよく使います。 これは今回のようにあらかじめデータをテーブルに格納しておくのではなく、 コードの走査時にデータベースを読んでFindするということですよね? 今回のように走査する件数が少ない場合にはDBアクセスに絡む オーバヘッドの方が大きいのではないかと思うのですが そんなこともないのでしょうか。 | ||||
|
投稿日時: 2004-08-19 14:11
いいえ。 あらかじめデータをテーブル(DataTable)に格納してPrimaryKeyを設定しておく。 コードの走査時に テーブル.Rows.Find(キー) != null で存在チェックが出来る。 50件程度ならわざわざ別のインデックスを用意する価値はあんまりない という意見でした。 | ||||
|
投稿日時: 2004-08-19 14:36
===>なちゃ様
レスありがとうございます。 >40回程度の検索で、1秒の差が出るということはまず考えられません。 確かに。^^; 今回の測定箇所は、純粋にループの前後ではないのですが、 これ以外のコードは不変なので、この2つのロジックの 違いによるスピード差であると結論づけてしまったのですが… ちなみに、測定したコードの概要を下記に掲載します(変数の定義等は一部省略します)。 Dim tm_start As Date Dim tm_end As Date tm_start = Now '@システム時刻をセット sSQL = "SELECT CODE FROM TBL_TEST" Try cmd_test.CommandText = sSQL dr_test = cmd_test.ExecuteReader() While dr_test.Read 'Aここを40回通過 chk_code = dr_test.Item(0) sw_hit = False ============================ if ht_Master.ContainsKey(chk_code) = Then 'テストケース1 'マスタに存在した場合の処理 End if ============================ For i = 0 To Master_Ctr - 1 'テストケース2 'Bここを1328回通過 If chk_code = Tbl_Master(i).code Then sw_hit = True Exit For End If Next If sw_np = True Then 'マスタに存在した場合の処理 End If ============================ End While Catch ex As Exception 'エラー処理 End Try dr_test.Close() tm_end = Now 'Cシステム時刻をセット MsgBox("tm_start = " & tm_start) MsgBox("tm_end = " & tm_end) とういう具合に表示した時刻の差が配列読みだと平均15秒、 ハッシュだと平均16秒でした。(5回ぐらいやった平均) で、実際には”マスタに存在した場合の処理”でテーブルに格納したり しているのですが、テストケース1、2以外の箇所のコードは同じですので この2つの検索方法の違いが速度の違いであると判断しました。 もしかしてミリ秒単位まで表示すべきだったのかな? 実際には数ミリ秒の差だったのかもしれません。^^; しかし、今回のケースでは配列読みの方が速かったというのは事実です。 | ||||
|
投稿日時: 2004-08-19 14:43
===>Jitta様
レスありがとうございます。 >検索対象が“昇順に並んでいる”のなら、クイックサーチや二分木サーチという手があります。検索されるデータの偏りにも因りますが、シーケンシャルサーチよりも早いことが期待されます。 イタイところを突かれました。^^; おっしゃる通りです。 検索アルゴリズムを勉強して出直してきます。 | ||||
|
投稿日時: 2004-08-19 14:45
===>todo様
レスありがとうございます。 ご教示頂いた方法でも実装してみて速度を比較してみようと思います。 アドバイスありがとうございました。 | ||||
|
投稿日時: 2004-08-19 16:40
お世話さまです。
todo様からアドバイス頂いたDataTableを用いた実装が実現したので、 シーケンシャル、ハッシュ、プライマリキーの3種類それぞれ5回づつ実行して 実行速度を比較検証してみました。 実装方法については自信がないのでご参考までに掲載致します。^^; ============================ Dim myDataSet As DataSet Dim myDataTable As DataTable = New DataTable("MasterTable") Dim myDataColumn As DataColumn Dim myDataRow As DataRow Dim PrimaryKeyColumns(0) As DataColumn myDataColumn = New DataColumn myDataColumn.DataType = System.Type.GetType("System.String") myDataColumn.ColumnName = "code" myDataColumn.ReadOnly = True myDataColumn.Unique = True myDataTable.Columns.Add(myDataColumn) PrimaryKeyColumns(0) = myDataTable.Columns("code") myDataTable.PrimaryKey = PrimaryKeyColumns myDataSet = New DataSet myDataSet.Tables.Add(myDataTable) '走査用マスタデータ読み込み … While dr_test.Read myDataRow = myDataTable.NewRow() myDataRow("code") = RTrim(dr_test.Item(0)) myDataTable.Rows.Add(myDataRow) End While … if myDataTable.Rows.Find(chk_code) Is Nothing Then Else 'マスタに存在した場合の処理 End If ============================ 今回はミリ秒単位まで計測して5回の平均値を取りました。 その結果… @シーケンシャルリード:8,229(単位:ミリ秒) Aハッシュ:8,174 BDataTable:8,238 となり、ハッシュが一番高速という結果でした。 しかもハッシュは5回とも速度が安定していました。 ちなみに、最速値と最遅値の差は下記のようになりました。 @シーケンシャルリード:211(単位:ミリ秒) Aハッシュ:90 BDataTable:150 今回のテスト環境としましては テストマシン(クライアント):Win Xp Professional Edition DBサーバ:Win2003+SQL Server2000 DBサーバはテスト用マシンで、私1人で専有的に使用してましたので、 外的影響を受ける可能性は低かったと思います。 (社内ネットワークトラフィックによる影響はあったかとは思いますが…) それと、全15回の計測結果に大きな変動がなかったことからも 比較環境は安定した状態に保てたのではないかと思います。 |