'WHERE A=x' 和 'WHERE A IN (x)' 之间的成本差异?

Cost difference between 'WHERE A=x' and 'WHERE A IN (x)'?

如果我想查找给定字段等于某个值的记录,我使用

SELECT * from TableName WHERE FieldName=value;

如果我想 select 匹配值列表的记录,我可以使用

SELECT * from TableName WHERE FieldName IN (value1, value2, ..., valueN);

避免WHERE FieldName = value1 OR FieldName = value2 OR... (已编辑,因为这似乎误导了问题的目的)

使用.eqp on似乎表明当我的列表只包含一个元素时,这两个查询是等价的。

这是真的吗?

如果是这样,我可以自由使用 WHERE FieldName IN (...) 并将值解析为逗号分隔列表(避免尾随逗号等)而不增加查询成本吗?

这似乎会大大简化我的查询编码,但令我惊讶的是 IN 运算符没有额外的复杂性成本,无论列表是否只有一个元素。

Edit:明确地说,我不会在任何情况下使用 OR - 如果我有一个值,那么之前我一直在使用第一种形式(FieldName=value)。如果我有多个值,我会使用 IN (val1, val2, ...)。根据评论,我似乎可以删除处理这些代码所需的代码,而只搜索 IN (value1).

当 SQLite 估计 IN 列表太短以至于其开销大于 OR-connected 系列相等比较的开销时,它将查询转换为后一种形式。 目前,这是针对大小为 1 或 2 的 IN 列表完成的。

EXPLAIN所示,单项代码相同:

sqlite> explain select * from t where x = 1;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     10    0                    00  Start at 10  
1     OpenRead       0     2     0     1              00  root=2 iDb=0; t
2     Rewind         0     8     0                    00               
3       Column         0     0     1                    00  r[1]=t.x     
4       Ne             2     7     1     (BINARY)       51  if r[1]!=r[2] goto 7
5       Copy           1     3     0                    00  r[3]=r[1]    
6       ResultRow      3     1     0                    00  output=r[3]  
7     Next           0     3     0                    01               
8     Close          0     0     0                    00               
9     Halt           0     0     0                    00               
10    Transaction    0     0     1     0              01  usesStmtJournal=0
11    TableLock      0     2     0     t              00  iDb=0 root=2 write=0
12    Integer        1     2     0                    00  r[2]=1       
13    Goto           0     1     0                    00               
sqlite> explain select * from t where x in (1);
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     10    0                    00  Start at 10  
1     OpenRead       0     2     0     1              00  root=2 iDb=0; t
2     Rewind         0     8     0                    00               
3       Column         0     0     1                    00  r[1]=t.x     
4       Ne             2     7     1     (BINARY)       51  if r[1]!=r[2] goto 7
5       Copy           1     3     0                    00  r[3]=r[1]    
6       ResultRow      3     1     0                    00  output=r[3]  
7     Next           0     3     0                    01               
8     Close          0     0     0                    00               
9     Halt           0     0     0                    00               
10    Transaction    0     0     1     0              01  usesStmtJournal=0
11    TableLock      0     2     0     t              00  iDb=0 root=2 write=0
12    Integer        1     2     0                    00  r[2]=1       
13    Goto           0     1     0                    00               

(如果 OR 项太多,SQLite 也会执行 opposite transformation。)