Update:
See this entry in my blog for performance details:
SELECT * FROM table WHERE field & number = number
SELECT * FROM table WHERE field | number = number
This index can be effective in two ways:
- To avoid early table scans (since the value to compare is contained in the index itself)
- To limit the range of values examined.
Neither condition in the queries above is sargable, this is the index will not be used for the range scan (with the conditions as they are now).
However, point 1
still holds, and the index can be useful.
If your table contains, say, 100
bytes per row in average, and 1,000,000
records, then the table scan will need to scan 100 Mb
of data.
If you have an index (with a 4
-byte key, 6
-byte row pointer and some internal overhead), the query will need to scan only 10 Mb
of data plus additional data from the table if the filter succeeds.
- The table scan is more efficient if your condition is not selective (you have high probablility to match the condition).
- The index scan is more efficient if your condition is selective (you have low probablility to match the condition).
Both these queries will require scanning the whole index.
But by rewriting the AND
query you can benefit from the ranging on the index too.
This condition:
field & number = number
can only match the fields if the highest bits of number
set are set in the field
too.
And you should just provide this extra condition to the query:
SELECT *
FROM table
WHERE field & number = number
AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1)
This will use the range for coarse filtering and the condition for fine filtering.
The more bits for number
are unset at the end, the better.