按位掩码与sqlite中的IN()效率?

时间:2011-03-04 11:30:50

标签: sql sqlite binary query-optimization mask

我有两种方法可以从数据库中选择一组条目:

  SELECT ... WHERE `level` IN (1,2,4,8) LIMIT ...;  

  SELECT ... WHERE `level` & mask LIMIT ...;

总共有4个'级别',编号为1,2,4,8(因为其他地方也可以使用相同的面具)。 IN()mask的大括号都可以包含4个级别中的一个或多个的任意集合。该列已编入索引。查询仍然比舒适更长,我们正在努力优化速度。

昨天一个人说决定使用天真的IN()导致最多四次比较,而我应该使用位掩码代替。今天我听说位掩码会完全阻止列上索引的优势,而且会慢得多。

你能告诉我哪种方法会更快吗?

1 个答案:

答案 0 :(得分:18)

你的问题很老了,但我仍然会回答它。

位掩码很可能会变慢,因为它必须计算出按位AND的计算,而IN将使用level索引值来查找它在括号内的参数中(我认为应该是单O(log(n))次操作)。

现在,你可能缺少的是,他们不会做同样的事情。

您的第一个查询只会检查level是1,2,4还是8。

您的第二个查询,或实际上类似于:

SELECT ... WHERE (`level` & mask) = mask LIMIT ...;

能够查找包含您想要的掩码的levels以及可能更多的掩码,在您的情况下,它可以检查1到15之间的所有值组合。因此,性能受到影响。


至于强制基准@AlanFoster建议,我不同意他。

使用以下任一方法为查询添加前缀要好得多:

  • EXPLAIN
  • EXPLAIN QUERY PLAN

检查SQLite匹配的行数。


更新

EXPLAIN QUERY PLAN SELECT * FROM ... WHERE level IN (2, 3);

SEARCH TABLE ... USING INDEX ..._level (level=?) (~20 rows)

EXPLAIN QUERY PLAN SELECT * FROM ... WHERE (level & 2) = 2;

SCAN TABLE ... (~500000 rows)

如您所见,按位AND运算符需要全表扫描。