使用 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=1
和1=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=1
和1=0
是在NHibernate
框架的某些部分中使用的SQL表达式,用于表示不会改变sql查询逻辑的空语句。不带子条件的Conjunction
生成1=1
表达式,不带子条件的Disjunction
生成1=0
表达式。如果未提供值,则 In() 会生成 1=0
表达式。
为避免此类优化,您可以更改创建这些空表达式的代码,并仅使用具有至少一个子条件的条件。
【讨论】:
以上是关于使用 OR 和 AND 进行 Sqlite 查询优化的主要内容,如果未能解决你的问题,请参考以下文章