您对我的代码有任何建议,您可能需要提高性能吗?这是.NET 2.0框架,DataTable绑定到DataGridview。数据通过.ReadXML()加载到Datatable中,它不是来自数据库。可以有80到100k的记录。 Terms()数组是用户为搜索传递的内容。所以“bob taco”是条款(0)=“bob”,条款(1)=“taco”。我有一个正则表达式,维护任何引用的术语。所以“bob taco”将在数组的一个元素上。有没有更好的办法?我尝试使用Dataview,因为它具有更好的性能,但看起来我不能使用LIKE运算符。欢迎任何建议,我真的想加快这一点。
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
答案 0 :(得分:3)
我检查过几个问题,并决定重写我的答案,以便更准确。 看看字符串处理。每次分配字符串新值时,都会创建一个全新的字符串。注意:您在循环中执行了许多大字符串操作。首先,你取得价值并做一些替换。然后你做一个大连接(“喜欢”部分)。尝试使用String.Format或 - 更好,更好 - 使用StringBuilder类。字符串操作会极大地降低性能。
答案 1 :(得分:1)
我建议不要创建过滤器,而是做类似
的操作foreach (DataRow row in ResidentTBL.Rows)
if (IsMatch(row))
newtable.ImportRow(row);
其中IsMatch方法实现过滤器中的逻辑。这应该会给你一个更好的调整控制。 DataTable拟合器设计为通用的,因此它们使用密钥样式算法的混搭。这并不总是找到记录的最佳方式。
注意,我的例子是C#,你需要调整VB,但我不是那么经文。
答案 2 :(得分:0)
我会在两个帐户上做不同的事情:首先,我会在数据库上运行查询,并仅使用正确(已过滤)的数据填充数据表。
其次,这种使用LIKE的方式将每次都通过所有记录,如果你有很多用户,它会变慢。我最终在这种情况下做的是实现一个“穷人搜索引擎”,它基本上将这些字段中的每个文本解析为单词并在另一个表中插入每个具有相应用户ID的单词。该表可以编入索引,搜索将直接使用'='而不是'LIKE'使其更快。
编辑:没有数据库使事情变得复杂。特别是因为你有很多数据,我不知道在搜索时是否有任何索引或优化。如果您有一种在请求之间缓存数据表的方法,则可以使用已分析的数据构建另一个数据表。只要用户正在搜索相同类型的令牌,它就应该可以工作,但是为了找到“bob taco”作为另一个旁边的两个单词,你需要在解析数据和搜索时保存单词的位置因此(它使它更复杂一点)。
例如:
ID, Text
1, Hangs out at Bob Taco joint
2, Hates Bob and his taco
会给出这样的东西:
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
所以现在你需要搜索包含bob和taco的ID,并且它们之间的差值应该是1.例如,由于Pos是2和5,所以不应该找到ID 2.
我使用SQL中的临时表来完成此操作。如果你只需要在内存中工作,可能会变得更难。
答案 3 :(得分:0)
您是否考虑过将搜索算法转换为使用LINQ to XML?这将为您节省DataTable的沉重感。
您可以简单地将XML文件加载到XmlDocument中,并对内存中XML对象中的元素执行LINQ查询。您可以在Linq-To-Xml tag page中找到更多问题和答案。也许从LINQ To XML: How Does It Work?
开始有一种真正可以帮助您的扩展方法:Contains()
如果您想继续使用DataTable,请执行以下info on using LINQ with DataTables。