【问题标题】:How to speed up a search in a large sqlite database如何加快在大型 SQLite 数据库中的搜索
【发布时间】:2014-04-16 17:48:39
【问题描述】:

我正在尝试开发一个能够在大型(300,000 人)sqlite 数据库中搜索人员的 Windows Phone 应用程序。 问题是找人需要半分钟。

您知道如何加快搜索速度吗?

这是我的代码:

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 是用户输入的两个单词。

提前谢谢你,

纳丁

【问题讨论】:

  • 给你的表添加索引怎么样!

标签: c# linq sqlite windows-phone


【解决方案1】:

这个查询有几个问题。

第一个是ToLower转换。在 SQL 中,这被翻译成类似lower(firstname) = :input1 的东西,如果存在这样的索引,这会阻止 sqlite 使用 firstname 列上的索引。在这种情况下,sqlite 需要扫描所有 30 万条记录,而不是直接使用索引查找一小部分记录。

为了缓解这种情况,您可以向contactslowercase_firstnamelowercase_lastname 添加其他列,并在插入或更新联系人表时在触发器中设置它们的值来自firstnamelastname。您应该为此列添加索引并按它们过滤以避免在 where 子句中调用 lower

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

  1. 翻译成类似:firstname like '%&lt;input1&gt;%'
  2. 或在内存中过滤

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

不幸的是,目前在 sqlite 中无法使用索引进行类似的搜索。所以这不能很快。

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

【讨论】:

    猜你喜欢
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 2012-09-19
    • 2022-01-23
    • 2011-12-31
    • 1970-01-01
    相关资源
    最近更新 更多