6

以下查询在 MySQL 中是否有效:

SELECT * FROM table WHERE field & number = number; 
# to find values with superset of number's bits

SELECT * FROM table WHERE field | number = number; 
# to find values with subset of number's bits

...如果该字段的索引已创建?

如果没有,有没有办法让它运行得更快?

4

3 回答 3

7

更新:

有关性能详细信息,请参阅我的博客中的此条目:


SELECT * FROM table WHERE field & number = number

SELECT * FROM table WHERE field | number = number

该索引可以通过两种方式发挥作用:

  1. 为了避免早期的表扫描(因为要比较的值包含在索引本身中)
    • 限制检查值的范围。

上述查询中的两个条件都不是sargable,这是索引不会用于范围扫描(条件与现在一样)。

但是,点1仍然成立,并且索引可能很有用。

如果您的表包含100平均每行的字节数和1,000,000记录,那么表扫描将需要扫描100 Mb数据。

如果您有一个索引(带有4-byte 键、6-byte 行指针和一些内部开销),如果过滤器成功,查询将只需要扫描10 Mb数据和表中的其他数据。

  • 如果您的条件不是选择性的(您很可能匹配条件),则表扫描会更有效。
  • 如果您的条件是选择性的(您匹配条件的可能性较低),则索引扫描会更有效。

这两个查询都需要扫描整个索引。

但是通过重写AND查询,您也可以从索引范围内受益。

这个条件:

field & number = number

number如果set的最高位也设置了,则只能匹配字段field

你应该只为查询提供这个额外的条件:

SELECT  *
FROM    table
WHERE   field & number = number
        AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1)

这将使用粗略过滤的范围和精细过滤的条件。

最后未设置的位number越多越好。

于 2009-09-28T15:34:39.437 回答
1

我怀疑优化器会想出那个...

也许您可以对这些查询调用 EXPLAIN 并确认我的悲观猜测。(当然要记住,大部分查询计划决策都是基于给定数据库的特定实例,即可变数量的数据和/或仅具有不同统计配置文件的数据可能会产生不同的计划)。

假设表有大量行,并且“按位”标准保持足够的选择性)当避免对每一行进行按位操作时,通过使用 IN 构造(或使用 JOIN )

类似的东西(概念,即未经测试)

CREATE TEMPORARY TABLE tblFieldValues
  (Field INT);

INSERT INTO tblFieldValues
   SELECT DISTINCT Field
   FROM table;

-- SELECT * FROM table WHERE field | number = number; 
-- now becomes
SELECT * 
FROM table t
WHERE field IN 
    (SELECT Field 
     FROM tblFieldValues 
     WHERE field | number = number); 

这种方法的全部好处需要用不同的用例来评估(所有这些用例在表中都有相当多的行,因为否则直接的“WHERE字段|数字=数字”方法就足够有效了),但我怀疑这可能会更快。如果不需要每次都重新创建“tblFieldValues”,则可以获得进一步的收益。高效创建此表当然意味着在原始表中的字段上建立索引。

于 2009-09-21T23:27:47.787 回答
0

我自己试过这个,按位运算不足以阻止Mysql在“字段”列上使用索引。但是,很可能正在对索引进行全面扫描。

于 2009-09-28T15:28:48.807 回答