Assume we have a simple mysql table(user) with fields:
id
rating
salary
I want to get 10 users with highest rating and salary with specified range(50-100), i.e in mysql it would be
SELECT id from user WHERE salary>50 and salary<100 ORDER by rating limit 0, 10
This runs for 20ms on 100K users table.
Assume I have same in redis:
Zlist rating (rating=>user_id)
Zlist salary (salary=>user_id)
All solutions I saw with redis include copying 100k salary Zlist, removing unneeded entries, and merging with 100k rating list, like
zinterstore 1 search salary
zremrange search -inf 50
zremrange search 100 +inf
zinterstore 2 search rating weights 0 1
zrange search 0 10
which is absolutely slow(why copy 100k elements to remove most of them?).
Is there any way to implement this at least comparably efficient with redis?
The use case you describe cannot be modeled elegantly in NoSQL solutions. It isn’t a Redis limitation.
Let me explain that a bit more. You are running range queries on one field, and sorting on another. This isn’t something NoSQL solutions are good at. For example, Google App Engine forbids such queries. Take a look at GAE Query Restrictions and read the section “Properties in Inequality Filters Must Be Sorted before Other Sort Orders”
Having said that, you can still efficiently run your queries, but the solution isn’t going to be elegant.
users_with_salary:10000-15000. This set will contain user ids who have salary in the given range.With redis 2.6 and lua scripting, you can even run this on the lua server.
In conclusion, if you want to run complex queries on your data, it is best to model it in a relational database.