使用 OR 和 AND 进行 Sqlite 查询优化

Posted

技术标签:

【中文标题】使用 OR 和 AND 进行 Sqlite 查询优化【英文标题】:Sqlite Query Optimization with OR and AND 【发布时间】:2012-11-12 16:26:37 【问题描述】:

执行以下查询需要 5 秒:

SELECT DISTINCT(Product.Name) FROM Product WHERE (0=1 OR Product.Number="prod11");

虽然以下只需要 15 毫秒:

SELECT DISTINCT(Product.Name) FROM Product WHERE (Product.Number="prod11");

有趣的是,以下也只需要 15 毫秒:

SELECT DISTINCT(Product.Name) FROM Product WHERE (1=1 AND Product.Number="prod11");

查询计划显示第一个查询使用全表扫描(出于某种未知原因),而第二个和第三个查询使用索引(如预期的那样)。

由于某种原因,Sqlite 似乎优化了“1=1 AND ...”,但并未优化“0=1 OR ...”。

如何让 Sqlite 也将索引用于第一个查询?

查询是由 NHibernate 构建的,因此很难更改它们...

Sqlite 版本是 Windows 的最新版本。

【问题讨论】:

0_o 在where 条件(即0=11=1)中有多余的语句是否有原因? 这只是更大查询的简化部分。 0=1 和 1=1 检查用于根据搜索条件启用或禁用 WHERE 子句的某些部分。在 NHibernate 方面,查询包含类似 (!criteria.FilterByProductNumber || criteria.ProductNumber == product.Number) && (!criteria.FilterByOtherProperty || criteria.OtherProperty = product.OtherProperty).. 的内容。 .." 导致插入常量 0=1 和 1=1 表达式。 Postgres 实际上还优化了 0=1 的情况以使用索引。我看不出为什么 Sqlite 可以优化 1=1 但不能优化 0=1...? 您是否尝试删除不必要的语句? 我无法删除它们。NHibernate 会创建它们。 【参考方案1】:

SQLite 的查询优化器相当简单,does not support OR expressions very well.

由于某种原因,如果它可以使用 覆盖 索引,它可以优化这个查询,所以试试这个:

CREATE INDEX TakeThatNHibernate ON Product(Number, Name)

【讨论】:

【参考方案2】:

1=11=0是在NHibernate框架的某些部分中使用的SQL表达式,用于表示不会改变sql查询逻辑的空语句。不带子条件的Conjunction 生成1=1 表达式,不带子条件的Disjunction 生成1=0 表达式。如果未提供值,则 In() 会生成 1=0 表达式。

为避免此类优化,您可以更改创建这些空表达式的代码,并仅使用具有至少一个子条件的条件。

【讨论】:

以上是关于使用 OR 和 AND 进行 Sqlite 查询优化的主要内容,如果未能解决你的问题,请参考以下文章

sqlite实现分页查询

Android中的SQLite查询来计算行数

如何使用 SQLite 使用 UNION ALL 和 ORDER BY 进行排序

SQLite 数据库的查看器/查询分析器 [关闭]

怎么查询sqlite里面第三行的数据

在同一个db上同时使用基于核心数据和sqlite c的api