我有一个用C#编写的Windows应用程序需要从数据库加载250,000行并提供“当你键入时搜索”功能,这意味着只要用户在文本框中输入内容,应用程序就需要搜索所有250,000记录(btw,每列1000个字符的单列)使用like
搜索并显示找到的记录。
我遵循的方法是:
1-该应用程序将所有记录加载到键入的List<EmployeeData>
while (objSQLReader.Read())
{
lstEmployees.Add(new EmployeesData(
Convert.ToInt32(objSQLReader.GetString(0)),
objSQLReader.GetString(1),
objSQLReader.GetString(2)));
}
2-在TextChanged事件中,使用LINQ
,我搜索(结合使用正则表达式)并将IEnumerable<EmployeesData>
附加到处于虚拟模式的ListView。
String strPattern = "(?=.*wood*)(?=.*james*)";
IEnumerable<EmployeesData> lstFoundItems = from objEmployee in lstEmployees
where Regex.IsMatch(Employee.SearchStr, strPattern, RegexOptions.IgnoreCase)
select objEmployee;
lstFoundEmployees = lstFoundItems;
处理3-4 RetrieveVirtualItem事件以显示ListView中的项目以显示该项目。
e.Item = new ListViewItem(new String[] {
lstFoundEmployees.ElementAt(e.ItemIndex).DateProjectTaskClient,
e.ItemIndex.ToString() });
虽然lstEmployees
加载相对较快(1.5秒)从SQL Server加载列表,但要搜索TextChanged,使用LINQ搜索需要7分钟以上。通过执行LIKE
搜索直接搜索SQL Server只需不到7秒。
我在这里做错了什么?如何更快地进行此搜索(不超过2秒)?这是我的客户的要求。所以,任何帮助都非常感谢。请帮忙......
答案 0 :(得分:3)
存储文本数据的数据库列是否有索引?如果是这样的话,类似于尼古拉斯描述的trie structure
的东西已经被使用了。 SQL Server中的索引是使用B+ trees
实现的,它的平均搜索时间为n的log 2的顺序,其中n是树的高度。这意味着如果表中有250,000条记录,则搜索所需的操作数为log base 2(250,000)或大约18条操作。
当您将所有信息加载到数据读取器中然后使用LINQ表达式时,它是一个线性运算,(O)n,其中n是列表的长度。最糟糕的情况是,这将是250,000次操作。如果您使用DataView,那么将有可用于帮助搜索的索引,这将大大提高性能。
在一天结束时,如果不会有太多针对数据库服务器提交的请求,请利用查询优化器来执行此操作。只要LIKE操作不是在字符串前面使用通配符(即LIKE %some_string
)(否定使用索引)并且表上有索引,您将获得非常快的性能。如果有太多请求将被提交到数据库服务器,则将所有信息放入DataView以便可以使用索引,或者使用上面提到的Tim的字典,其搜索时间为O(1 )(大约一),假设字典是使用哈希表实现的。
答案 1 :(得分:2)
请参阅我对this question的回答。如果您需要即时响应(即,与用户类型一样快),将数据加载到内存中可能是一个非常有吸引力的选择。它可能会使用一点内存,但速度非常快。
即使有很多字符(250K记录* 1000),还有多少唯一值?基于键的内存结构与指向匹配这些键的记录的指针实际上不一定非常大,甚至可以解释这些键的排列。
如果数据真的不适合内存或频繁更改,请将其保存在数据库中并使用SQL Server全文索引,这将比LIKE
更好地处理此类搜索。假设从应用程序到数据库的快速连接。
全文索引提供了一组强大的运算符/表达式,可用于使搜索更加智能化。它可以使用免费的SQL Expression Edition,它可以处理多达10GB的数据。
答案 2 :(得分:2)
答案 3 :(得分:0)
如果可以对记录进行排序,您可能希望使用二进制搜索,这对于大型数据集来说要快得多。 .NET集合中有几种实现,如List<T>
和Array
。