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

SF.*_*SF. 10 sql sqlite binary mask query-optimization

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

  SELECT ... WHERE `level` IN (1,2,4,8) LIMIT ...;  
Run Code Online (Sandbox Code Playgroud)

要么

  SELECT ... WHERE `level` & mask LIMIT ...;
Run Code Online (Sandbox Code Playgroud)

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

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

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

Ali*_*xel 18

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

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

现在,你可能会遗漏的是,他们不会做同样的事情.

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

你的第二个查询,或实际上是这样的:

SELECT ... WHERE (`level` & mask) = mask LIMIT ...;
Run Code Online (Sandbox Code Playgroud)

能够查找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)
Run Code Online (Sandbox Code Playgroud)

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

SCAN TABLE ... (~500000 rows)
Run Code Online (Sandbox Code Playgroud)

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

  • +1表示解释和澄清IN和MASK之间的区别 (2认同)