2009-08-04 23 views
1

パフォーマンスを向上させる必要があるかもしれない以下のコードについて、ご意見はありますか?これは.NET 2.0フレームワークであり、DataTableはDataGridviewにバインドされています。データは、データベースから来ていない.ReadXML()を介してDatatableにロードされます。 80から100kまでのレコードはどこにもあります。 Terms()配列は、ユーザーが検索に渡した配列です。したがって、 "bob taco"はterms(0)= "bob"、terms(1)= "taco"となります。私は引用された用語を維持する正規表現を持っています。したがって、 "bob taco"は配列の1つの要素になります。より良い方法がありますか?私はDataviewを使用してみましたが、これはパフォーマンスが向上していますが、LIKE演算子を使用できるようには見えませんでした。どんな提案も大歓迎です、私はこれを少しスピードアップしたいと思います。Datagridviewにデータテーブルをバインドする

Public Function Search(ByVal Terms() As String, ByRef ResidentTBL As DataTable) As DataTable 
     'Dim t As Long = Now.Ticks 

     Dim j As Integer 
     Dim newdt As New DataTable("Users") 
     Dim newtable As New DataTable 
     newtable = ResidentTBL.Clone 

     Dim termsceiling As Integer 
     termsceiling = Terms.GetUpperBound(0) 
     Dim filterstr As String = String.Empty 
     Dim foundrows() As DataRow 
     Dim sortOrder As String = "displayname ASC" 
     Dim tempstr As String 

     For j = 0 To termsceiling 
      'remedy any invalid sql characters 
      tempstr = Terms(j).Trim.ToUpper 
      tempstr = tempstr.Replace("'", "''") 
      tempstr = tempstr.Replace("*", "") 
      tempstr = tempstr.Replace("%", "") 

      'assemble the sql query 

      filterstr = filterstr & _ 
     "((column1 LIKE '" & tempstr & "%') OR " & _ 
     "(column2 LIKE '" & tempstr & "%') OR " & _ 
     "(column3 LIKE '" & tempstr & "%') OR " & _ 
     "(column4 LIKE '" & tempstr & "%') OR " & _ 
     "(column5 LIKE '" & tempstr & "%') OR " & _ 
     "(column6 LIKE '" & tempstr & "%') OR " & _ 
     "(column7 LIKE '" & tempstr & "%') OR " & _ 
     "(column8 LIKE '" & tempstr & "%') OR " & _ 
     "(column9 LIKE '" & tempstr & "%') OR " & _ 
     "(column10 LIKE '" & tempstr & "%'))" 


      'if there are further iterations append an AND (user typed more than one term) 
      If termsceiling > 0 And j <> termsceiling Then 
       filterstr = filterstr & " AND " 
      End If 
     Next j 

     filterstr = "(" & filterstr & ")" 'wrap the entire query 

     foundrows = ResidentTBL.Select(filterstr, sortOrder) 

     For i = 0 To foundrows.Length - 1 
      newtable.ImportRow(foundrows(i)) 
     Next i 

     newdt = newtable 

     'Begin Debugging Code: 
     't = Now.Ticks - t 
     'MessageBox.Show("Took " & (t/10000000) & " seconds.") 
     'End Debugging Code: 

     Return newdt 
    End Function 
+1

BTW:Termが1次元配列の場合、termceiling変数内にLenghtプロパティを使用できます。 – smok1

答えて

0

私はこれを2つのアカウントで別々に行います。まず、データベースでクエリを実行し、正しい(フィルタを適用した)データのみでデータテーブルを埋めます。

第2に、LIKEを使用するこの方法は、すべてのレコードを毎回移動し、多くのユーザーがいる場合は遅くなります。私がこの状況でやっているのは、基本的にこれらのフィールドの各テキストを単語に分解し、対応するユーザーIDを持つ単語を別のテーブルに挿入する「貧弱な検索エンジン」を実装することです。その表は索引付けすることができ、検索は「=」で直接行われ、「好き」ではなくなります。

:データベースを持っていないと物事が複雑になりません。特に、多くのデータを持っているので、このような検索の際にインデックスや最適化があるかどうかはわかりません。リクエスト間でデータテーブルをキャッシュする方法がある場合は、解析されたデータで別のデータテーブルを作成できます。ユーザーが同じ種類のトークンを検索している限り、それはうまくいくはずですが、「ボブタコ」を2つの単語の順に検索するには、データを解析して検索するときに単語の位置を保存する必要がありますそれに応じて(少し複雑になります)。例えば

:だから今はボブとタコスの両方が含まれているのIDを検索する必要があり、それらの順位値の差がすべき

ID, Key, Pos 
1, Hangs, 1 
1, out, 2 
1, at, 3 
1, Bob, 4 
1, Taco, 5 
1, joint, 6 
2, Hates, 1 
2, Bob, 2 
2, and, 3 
2, his, 4 
2, taco, 5 

ID, Text 
1, Hangs out at Bob Taco joint 
2, Hates Bob and his taco 

はこのような何かを与えるだろうたとえば、Posは2と5であるため、ID 2は検出されません。

これはSQLの一時テーブルを使用して行いました。メモリだけで作業する必要がある場合は、難しくなる可能性があります。

+0

ありがとうございます。残念ながら、データベースはありません。これはXMLファイルから取り込まれます。私は.readxmlを使ってそれをデータテーブルに吸い込みます。私はそれに応じてそれをフィルタリングします。私がLIKEを使用している理由は、ユーザーが何を私に渡すのか分かりません。フリーフローティングテキスト検索です。だから、彼らは電話番号、ユーザーID、またはファーストネームを入れることができます。私は彼らが何を入れようとしているのか分かりません。あなたの "ポーマー検索"はまだ動作しますか? –

3

私はいくつかの問題をチェックし、より正確な答えを書き直すことにしました。 文字列処理を見てください。文字列に新しい値を割り当てるたびに、新しい文字列が作成されます。注:ループ内で多数の大きな文字列操作を実行しています。まず、あなたは価値を持ち、いくらか交換します。次に、大きな連結( "like"セクション)を行います。 String.Formatを使用するか、StringBuilderクラスを使用してください。文字列操作は、パフォーマンスを著しく低下させる可能性があります。

+0

素晴らしい提案。 +1 –

+0

私は文字列ビルダーの代わりに行う方法を知っていますが、フィルター上のすべてのコンカットを行う最良の方法は何ですか? –

+2

Use Appendメソッド: http://msdn.microsoft.com/en-us/library/b4sc8ca8(VS.80).aspx – smok1

1

私は、フィルタを作成し、代わりにIsMatchメソッドは、あなたのフィルター内のロジックを実装し

foreach (DataRow row in ResidentTBL.Rows) 
    if (IsMatch(row)) 
      newtable.ImportRow(row); 

のようなものをやっていないお勧めします。これはあなたにもう少し細かい制御を与えるはずです。 DataTableのfitlersは汎用的に設計されているので、キースタイルのマッシュアップアルゴリズムを使用します。それは常にレコードを見つけるのに最も最適な方法ではありません。

注意、私の例では、C#で、あなたは、VBのために調整する必要がありますが、私は中に詩としてはないです。

+0

明確にするために、文字列でIndexOfを使用してLIKE演算子を置き換えることができます。 – Kleinux

+0

フィルタを含めてコードスニペット全体を投稿できますか?私はそれをベンチマークするでしょう、それがより良いパフォーマンスをもたらすなら、私は答えとしてマークします。それはC#ですることができます。 –

+0

笑...私は彼があなたのためにあなたの仕事をしなければならないとは思わない。彼はそうだけど、Filterはあなたがやろうとしていることを本当に意図したものではなく、Kleinuxの方法は少し速いだろう。 –

0

あなたはXMLにLINQを使用するために、検索アルゴリズムを変換すると考えられていますか?これにより、DataTableの負荷が軽減されます。

XMLファイルをXmlDocumentにロードし、メモリ内XMLオブジェクトの要素に対してLINQクエリを実行するだけで簡単に実行できます。より多くの質問と回答はLinq-To-Xml tag pageにあります。 Contains()

あなたはDataTableの実装を継続したい場合は、ここでinfo on using LINQ with DataTablesよります:おそらくLINQ To XML: How Does It Work?

本当にあなたを助ける拡張メソッドがありますから開始します。

+0

私は大好きですが、それは.net 2.0です。 –

関連する問題