如何在大型sqlite数据库中加快搜索速度
本文关键字:搜索 速度 数据库 大型 sqlite | 更新日期: 2023-09-27 17:58:30
我正在尝试开发一款Windows Phone应用程序,该应用程序能够在大型(300000人)sqlite数据库中搜索人员。问题是要花半分钟才能找到一个人。
你知道我怎样才能加快搜索速度吗?
这是我的代码:
var queryname = conn.Table<contacts>().Where(
x =>
(
((x.firstName.ToLower() == input1) && (x.lastName.ToLower() == input2))
|| ((x.firstName.ToLower() == input2) && (x.lastName.ToLower() == input1))
|| ((x.firstName.ToLower() == input1) && (x.lastName.ToLower().Contains(input2)))
|| ((x.lastName.ToLower().Contains(input1)) && (x.firstName.ToLower() == input2))
));
var resultname = await queryname.ToListAsync();
Person1.Content = null;
foreach (var item in resultname)
{
outputname = string.Format("{0} {1}", item.firstName, item.lastName);
}
输入1和2是用户输入的两个单词
提前谢谢你,
Nadine
此查询存在几个问题。
第一种是CCD_ 1转换。在SQL中,这被转换为类似于lower(firstname) = :input1
的内容,这样可以防止sqlite在存在firstname列索引的情况下使用该索引。在这种情况下,sqlite需要扫描所有300k条记录,而不是直接使用索引找到一小部分记录。
为了缓解这种情况,您可以在contacts
表lowercase_firstname
和lowercase_lastname
中添加额外的列,并在插入或更新联系人表时从触发器中的firstname
和lastname
中设置它们的值。您应该为这些列添加索引并根据它们进行筛选,以避免在where子句中调用lower
。
第二个问题是CCD_ 9的使用。我不确定LINQ究竟是如何将其转换为SQL的,但它没有太多选择。它要么
- 翻译成类似于:
ToLower
0 - 或进行内存中过滤
第二个选项要求从数据库中读取所有记录,但这不会很快。第一个选项不使用firstname列上的现有索引,并且需要完整的表扫描。
不幸的是,目前在sqlite中没有办法像使用索引一样进行搜索。所以这不可能很快。
一种选择是不允许在名字和姓氏中搜索,只允许按名字的第一个字母搜索。因此,如果input1=Rita,则用户能够找到Rita
而不能找到Margarita
。有了这个限制,可以通过发出像lowercase_firstname between 'Rita' and 'Rita{'
这样的范围查询来使用索引进行搜索(这里{
是z
后面的字母)。这将有助于您在LINQ中表达between。