SCAN vs KEYS performance in Redis
A number of sources, including the official Redis documentation, note that using the KEYS
command is a bad idea in production environments due to possible blocking. If the approximate size of the dataset is known, does SCAN
have any advantage over KEYS
?
For example, consider a database with at most 100 keys of the form data:number:X
where X
is an integer. If I want to retrieve all of these, I might use the command KEYS data:number:*
. Is this going to be significantly slower than using SCAN 0 MATCH data:number:* COUNT 100
? Or are the two commands essentially equivalent in this circumstance? Would it be accurate to say that SCAN
is preferable to KEYS
because it protects against the scenario where an unexpectedly large set would be returned?
Solution 1:
You shouldn't care about current command execution but about the impact to all other commands, since Redis processes commands using a single thread (i.e. while a command is being executed all others need to await until executing one ends).
While keys
or scan
might provide you similar or identical performance executed alone in your case, some milliseconds blocking Redis will significantly decrease overall I/O.
This the main reason to use keys
for development purposes and scan
on production environments.
OP said:
"While keys or scan might provide you similar or identical performance executed alone in your case, some milliseconds blocking Redis will significantly decrease overall I/O." - This sentence seems to indicate that one command blocks Redis, and the other doesn't, which can't be the case. If I am guaranteed 100 results from my call to KEYS, in what way is it worse than SCAN? Why do you feel that one command is more prone to blocking?
There should be a good difference when you can paginate the search. It's not the same being forced to get 100 keys in a single pass than being able to implement pagination and get 100 keys, 10 by 10 (or 50 and 50). This very small interruption can let other commands sent by the application layer be processed by Redis. See what Redis official documentation says about this:
Since these commands allow for incremental iteration, returning only a small number of elements per call, they can be used in production without the downside of commands like KEYS or SMEMBERS that may block the server for a long time (even several seconds) when called against big collections of keys or elements
.
Solution 2:
The answer is in the SCAN
documentation
These commands allow for incremental iteration, returning only a small number of elements per call, they can be used in production without the downside of commands like
KEYS
orSMEMBERS
that may block the server for a long time (even several seconds) when called against big collections of keys or elements.
So ask for small chunks of data rather than getting whole of it
Also as Matías Fidemraizer pointed out, Redis is single threaded and KEYS
is a blocking call thus blocking any incoming requests for operation until execution of KEYS
is done.
Whether your data is small or not, it never hurts to apply best practices.