【问题标题】:bitwise mask vs IN() efficiency in sqlite?sqlite中的按位掩码与IN()效率?
【发布时间】:2011-07-08 18:22:36
【问题描述】:

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

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

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

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

昨天有人说决定使用幼稚的 IN() 会导致最多四次比较,我应该使用位掩码。今天听说位掩码会完全抵消列索引的优势,而且会慢很多。

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

【问题讨论】:

    标签: sql sqlite binary query-optimization mask


    【解决方案1】:

    你的问题已经很老了,但我还是会回答。

    位掩码很可能会更慢,因为它必须计算按位与的计算,而 IN 将使用 levelindexed 值在随附的参数中查找它在括号内(我认为应该是单个 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)
    

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

    【讨论】:

    • +1 建议解释和澄清 IN 和 & MASK 之间的区别
    • 有用的调查!
    • 对一个有点老的问题的一个有点老的答案来引发一个新的辩论:)。我认为(level & mask) = mask 应该在O(klog(n)) 中完成,其中k 是掩码的位长。提出这个问题的另一种方法是给我所有具有掩码所有位的级别值,如果我用列替换位,它将是:给我列等于掩码列的所有级别。如果我对其应用哈希优化,我们还可以说它是O(log(n)),与IN 查询的性能相同,但与您提到的结果不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    相关资源
    最近更新 更多