基于主键列表的高效sqlite查询

时间:2016-07-05 08:51:46

标签: performance sqlite select primary-key

为了根据ID列表(即不同的主键)查询sqlite表,我使用以下语句(基于Chinook Database的示例):

SELECT * FROM Customer WHERE CustomerId IN (1,2,3,8,20,35)

但是,我的ID实际列表可能会变得相当大(> 1000)。因此,我想知道使用IN语句的这种方法是否最有效,或者是否有更好/优化的方法来基于主键列表查询sqlite表。

3 个答案:

答案 0 :(得分:1)

如果IN中的元素数量足够大,SQLite会为它们构造一个临时索引。这可能比手动创建temporary table更有效。

IN列表的长度仅限于maximum length of an SQL statement和内存。

答案 1 :(得分:0)

因为您编写的语句不包含任何关于如何找到行的SQLite的指令,您希望"优化"并不存在 - 没有什么可以优化的。规划检索数据的最佳算法的工作属于SQLite查询优化器。

某些数据库在其查询优化器中确实存在特性,这可能会导致性能问题,但我不希望SQLite在查找这个简单查询的正确算法时遇到任何问题,即使IN列表中有很多值也是如此。如果您发现存在性能问题,我只会担心尝试将查询优化器引导到另一个执行计划。

答案 2 :(得分:0)

SQLite Optimizer Overview

IN (expression-list)确实使用索引(如果可用)。

除此之外,我无法从中收集任何保证,因此以下内容需要进行绩效评估。

轴1:如何传递表达式列表

  • hardocde as string。用于int到字符串转换和字符串到int解析的开销
  • 绑定参数(即语句为... WHERE CustomerID in (?,?,?,?,?,?,?,?,?,?....),这比使用硬编码值更容易从预定义字符串构建)。阻止int→string→int转换,但参数数量的默认限制为999.这可以增加SQLITE_LIMIT_VARIABLE_NUMBER,但可能会导致分配过多。
  • 临时表。在准备语句之后,可能比上述任何方法效率低,但如果花费大部分时间准备语句,这并没有帮助

轴2:声明优化

如果在多个查询中使用相同的表达式列表而不是更改CustomerIDs,则以下之一可以提供帮助:

  • 重复使用带有硬编码值的 prepared statement (即不通过1001参数)
  • 为具有索引的CustomerID创建一个临时表(因此索引创建一次,而不是为每个查询动态创建)

如果表达式列表与每个查询不同,那么最好让SQLite完成它的工作。以下可能是一项改进

  • 为表达式列表
  • 创建临时表
  • 使用union all
  • 批量插入表达式列表元素
  • 使用子查询

(根据我对SQLite的经验,我预计它会与平价或稍差一样)

Axis 3 询问理查德

sqlite邮件列表(是的,我知道,这种技术甚至比旋转手机还要早!)非常活跃,通常都是出色的建议,包括来自SQLite的作者。 90%的几率有人会解雇你屁股"在之前测量问一个问题!",10%的几率有人给你详细的见解。