以下查询在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
...如果已创建该字段的索引?
如果没有,有没有办法让它跑得更快?
答案 0 :(得分:6)
<强>更新强>
有关效果详情,请参阅我的博客中的此条目:
SELECT * FROM table WHERE field & number = number
SELECT * FROM table WHERE field | number = number
该指数可以通过两种方式有效:
上述查询中的任何条件都不是 sargable ,这是索引不会用于范围扫描(条件与现在一样)。
但是,点1
仍然有效,索引也很有用。
如果您的表格中包含平均每行100
个字节和1,000,000
个记录,那么表格扫描将需要扫描100 Mb
个数据。
如果你有一个索引(4
- 字节键,6
- 字节行指针和一些内部开销),查询将只需要扫描10 Mb
个数据加上如果过滤器成功,表中的其他数据。
这两个查询都需要扫描整个索引。
但是通过重写AND
查询,您也可以从索引的范围中受益。
这个条件:
field & number = number
number
中设置field
集的最高位,则只能匹配字段。
你应该只为查询提供这个额外的条件:
SELECT *
FROM table
WHERE field & number = number
AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1)
这将使用粗滤波范围和精细滤波条件。
number
的最后一位未设置的位数越多越好。
答案 1 :(得分:1)
我怀疑优化器会想出那个......
也许你可以在这些查询上调用EXPLAIN并确认我的悲观猜测。 (当然记住,很多查询计划决策都是基于给定数据库的特定实例,即可变数据量和/或只是具有不同统计概况的数据可能会产生不同的计划)。
假设表具有大量行,并且“bitwised”标准保持足够的选择性)通过使用IN构造重写查询(或者使用IN构造重写查询),当避免对每一行进行按位操作时,可以实现可能的优化。加入)
类似的东西(概念性的,即没有经过测试的)
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”,则可以实现进一步的增益。当然,有效创建此表意味着在原始表中使用Field的索引。
答案 2 :(得分:0)
我自己尝试了这一点,并且按位操作不足以阻止Mysql在“field”列上使用索引。但是,很可能正在对指数进行全面扫描。