如何在大型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

如何在大型sqlite数据库中加快搜索速度

此查询存在几个问题。

第一种是CCD_ 1转换。在SQL中,这被转换为类似于lower(firstname) = :input1的内容,这样可以防止sqlite在存在firstname列索引的情况下使用该索引。在这种情况下,sqlite需要扫描所有300k条记录,而不是直接使用索引找到一小部分记录。

为了缓解这种情况,您可以在contactslowercase_firstnamelowercase_lastname中添加额外的列,并在插入或更新联系人表时从触发器中的firstnamelastname中设置它们的值。您应该为这些列添加索引并根据它们进行筛选,以避免在where子句中调用lower

第二个问题是CCD_ 9的使用。我不确定LINQ究竟是如何将其转换为SQL的,但它没有太多选择。它要么

  1. 翻译成类似于:ToLower0
  2. 或进行内存中过滤

第二个选项要求从数据库中读取所有记录,但这不会很快。第一个选项不使用firstname列上的现有索引,并且需要完整的表扫描。

不幸的是,目前在sqlite中没有办法像使用索引一样进行搜索。所以这不可能很快。

一种选择是不允许在名字和姓氏中搜索,只允许按名字的第一个字母搜索。因此,如果input1=Rita,则用户能够找到Rita而不能找到Margarita。有了这个限制,可以通过发出像lowercase_firstname between 'Rita' and 'Rita{'这样的范围查询来使用索引进行搜索(这里{z后面的字母)。这将有助于您在LINQ中表达between。