I'm just starting to use redis and I want to retrieve a part of the key-value pairs (like a SELECT or find).
My plan is to save the relevant keys in a set. So I will use SMEMBERS, get the keys and then use MGET for each element.
Is it the proper way to achieve my goal or there's a better built-in mechanism?
Thanks.
Yes, that's the basic approach to "indexing" in Redis. If your set is
large, you'd want to use SSCAN instead of SMEMBERS. Also, don't use a
single MGET for everything, but rather make batches of constant size
(e.g. 100). These two methods will allow better concurrency.
– Itamar Haber
Related
I want to get from redis all the keys that the number of elements in their list
(Each value is a list type) has more than x items?
How do I do that?
Any simple way or just have to use lua? if lua - how?
There are many ways to achieve that, each with its own pros and cons. The first decision you have to make is whether you want to have the answer to your query pre-prepared or computed ad-hoc.
For pre-prepared, you'll have to maintain an index of the lists by length. For ad-hoc, you'll have to scan all the lists and get their lengths at runtime.
Assuming you are trying to implement an ad-hoc query, a server-side Lua script is a good choice if you already know how. If not, you can either learn it (https://redis.io/commands/eval) or use a regular Redis client in your language of choosing.
Given that you need to traverse the keyspace and that the script is going to block until it has finished regardless of what it is doing - is it better to just use 'keys' and get this over with as quickly as possibly as opposed to multiple calls to 'scan'?
You're not supposed to iterate the entire keyspace, as this is a slow operation. If you really must do that, and insist on using server-side Lua, you'd be better off with SCAN, as it will not consume as much memory as KEYS may consume (for the reply).
I have a set of strings, which I was planning to store in a redis set. What I want to do is to check if any of these strings [s] is present inside a subject string ( say S1 ).
I read about SSCAN in redis but it allows me to search if any set member matches a pattern. I want the opposite way round. I want to check if any of the patterns matches my string. Is this possible?
What you want to do is not possible, but if your plan is to match prefixes, like in an autocomplete, you can take a look at sorted sets and ZRANGEBYLEX. You can take a look at this example. Even though it's not working right now, the code is very simple.
There are several ways to do it, it just depends how you want it done. SSCAN is a perfectly legitimate approach where you do the processing client-side and potentially over the network. Depending on your requirements, this may or may not be a good choice.
The opposite way is to let Redis do it for you, or as much as possible, to save on bandwidth, latency and client cpu. The trade off is, of course, having Redis' cpu do it so it may impact performance in some cases.
When it comes to letting Redis do the work, please first understand that the functionality you're describing is not included in it. So you need to build your own and, again, that depends on your specific use case (e.g. how big are s and S1, is S1 indexable as well, ...). Without this information it is hard to make accurate recommendations but the naive (mine) approach would be to use Lua for the job. The script's logic should either check all permutations of S1 for existence in s with SISMEMBER, or, do Lua pattern matching of all of s's members to S1.
This solution, of course, has plenty of room for optimization if some assumptions/rules are set.
Edit: Sorted sets and ZLEX* stuff are also possibly good for this kind of thing, as #Soveran points out. To augment his example and for further inspiration, see here for a reversed version and think of the possibilities :) I still can't understand how someone didn't go and implement FTS in Redis!
I'm wondering if the way we "design" keys in Redis can impact performance and scalability.
For example, if I store content related to "users" under keys like "user:<user_id>" and content related to say, groups, under keys like "group:<group_id>", all my keys will start with either "user:" or "group:".
Will this have a negative impact on the way Redis hashes keys internally?
There is no negative impact. Precisely the design you mention is recommended in the official Redis docs, which are quite clear on this:
Very long keys are not a good idea, for instance a key of 1024 bytes is a bad idea ...
but, read on:
Very short keys are often not a good idea. There is little point in writing "u1000flw" as a key if you can instead write "user:1000:followers". The latter is more readable and the added space is minor compared to the space used by the key object itself and the value object. While short keys will obviously consume a bit less memory, your job is to find the right balance.
Try to stick with a schema. For instance "object-type:id" is a good idea, as in "user:1000". Dots or dashes are often used for multi-word fields, as in "comment:1234:reply.to" or "comment:1234:reply-to".
(Emphases mine.)
See also: Redis key naming conventions?
As it is basically a hash table under the hood, there is nothing analogous to a SQL-style WHERE. That's where bad design could effect performance.
No, it shouldn't be any issue with prefixing your keys like that. Redis uses a hash table internally which in turn uses a proper hash function (one of the murmur hashes if I recall correctly) that won't budge by prefixes.
I'm trying to use Redis as a primary database for a small game I'm making (mostly to mess around with programming and using Redis).
However I came across a scenario that I couldn't find an answer to:
I wish to store a list of the names of different maps that people can be on (not many of them) along with their id. Note: I never need to get the ID from the name.
The two ways I believe this can be done are either storing the information as a string or as a hash.
i.e:
1) String based:
set maps:0 "Main"
set maps:1 "Island"
etc (and maybe a maps:id to
store an auto increment value)
2) Hash based:
hset maps "0" "Main"
hset maps "1" "Island"
etc
My question is which way seems the best. Given that there will never be that many maps I'm leaning towards the single hashed object. Partially because this provides a nice method to return all the maps in existence. But is there any particular reason that the string based queries would be more useful.
Hopefully you can give me some clear information.
Thank you,
Pluckerpluck
The String based values are actually discouraged because it consumes a lot more memory than a hash.
Redis optimizes small hashes and encodes them in a memory efficient manner. This encoding is called zipmap (or ziplist in redis 2.6). See http://redis.io/topics/memory-optimization, specially the section "Use hashes when possible".