Why is sscan showing keys that don't exist? - redis

I run sscan A 0, and the first key in the list is X. But X does not exist. ttl X gives -2, exists X gives 0, get X gives (nil), and yet when I run sscan it still shows up in the list.
More, info keyspace says that there are 594620 keys total. However, scard A says there are 1211593. So, there are twice as many keys in the set than there are in the whole database? How does that work???
How can I get an accurate count of the number of keys in the set?

You're confusing the members of a set with keys in the database. The only key here is A. The members of A are not keys.
Now, it may be that you're using the names of keys as the string-valued members of your A, but nevertheless they are not keys.

Related

IndexedDB using an index versus a key range?

In indexedDB, if the keys are arrays of integers such as [n,0] through [n,m], for operations that involve getting all the records in which the first element of the array key is n or opening a cursor on the same set of records, is there any advantage to using an index on an additonal property that stores n over using a key range?
Reasons to think an index may not be better include that the browser has to maintain the index for each change to the object store, an additional property has to be added to each record to store already stored data n, and little may be gained since the keys in the index will always point to consecutive records in the object store rather than dispersed throughout.
If the number of different values of n are likely no more than 1,000 and for m no more than 50, is using an index superior to a key range?
Thank you.
I guess the purpose of indexedDB is to have object store locally.
It is not sql that you need to update columns in every object.
since you change the object structure (saying by adding property)
it is true that all the objects in the store must be rewriten as you said...
emm well... another option for you is to update the db with another store
which contain somthing similar to forien key in sql or uniqe key which store the other stored objects extentions... and in it every obj item is also supposed to be same structured.
I think this is the point you start to use onupgradeneeded intansively.

Composite Primary Key equivalent in Redis

I'm new to nosql databases so forgive my sql mentality but I'm looking to store data that can be 'queried' by one of 2 keys. Here's the structure:
{user_id, business_id, last_seen_ts, first_seen_ts}
where if this were a sql DB I'd use the user_id and business_id as a primary composite key. The sort of querying I'm looking for is a
1.'get all where business_id = x'
2.'get all where user_id = x'
Any tips? I don't think I can make a simple secondary index based on the 2 retrieval types above. I looked into commands like 'zadd' and 'zrange' but there isn't really any sorting involved here.
The use case for Redis for me is to alleviate writes and reads on my SQL database while this program computes (doing its storage in redis) what eventually will be written to the SQL DB.
Note: given the OP's self-proclaimed experience, this answer is intentionally simplified for educational purposes.
(one of) The first thing(s) you need to understand about Redis is that you design the data so every query will be what you're used to think about as access by primary key. It is convenient, in that sense, to imagine Redis' keyspace (the global dictionary) as something like this relational table:
CREATE TABLE redis (
key VARCHAR(512MB) NOT NULL,
value VARCHAR(512MB),
PRIMARY KEY (key)
);
Note: in Redis, value can be more than just a String of course.
Keeping that in mind, and unlike other database models where normalizing data is the practice, you want to have your Redis ready to handle both of your queries efficiently. That means you'll be saving the data twice: once under a primary key that allows searching for businesses by id, and another time that allows querying by user id.
To answer the first query ("'get all where business_id = x'"), you want to have a key for each x that hold the relevant data (in Redis we use the colon, ':', as separator as a matter of convention) - so for x=1 you'd probably call your key business:1, for x=a1b2c3 business:a1b2c3 and so forth.
Each such business:x key could be a Redis Set, where each member represents the rest of the tuple. So, if the data is something like:
{user_id: foo, business_id: bar, last_seen_ts: 987, first_seen_ts: 123}
You'd be storing it with Redis with something like:
SADD business:bar foo
Note: you can use any serialization you want, Set members are just Strings.
With this in place, answering the first query is just a matter of SMEMBERS business:bar (or SSCANing it for larger Sets).
If you've followed through, you already know how to serve the second query. First, use a Set for each user (e.g. user:foo) to which you SADD user:foo bar. Then SMEMBERS/SSCAN and you're almost home.
The last thing you'll need is another set of keys, but this time you can use Hashes. Each such Hash will store the additional information of the tuple, namely the timestamps. We can use a "Primary Key" made up of the bussiness and the user ids (or vice versa) like so:
HMSET foo:bar first 123 last 987
After you've gotten the results from the 1st or 2nd query, you can fetch the contents of the relevant Hashes to complete the query (assuming that the queries return the timestamps as well).
The idiomatic way of doing this in Redis is to use a SET for each type of query you want to do.
In your case you would create:
a hash for each tuple (user_id, business_id, last_seen_ts, first_seen_ts)
a set with a name like user:<user_id>:business:<business_id>, to store the keys of the hashes for this user and this business (you have to add the ID of the hashes with SADD)
Then to get all data for a given user and business, you have to get the SET content with SMEMBERS first, and then to GET every HASH whose ID is in the SET.

What does the "minimality" mean in database candidate keys?

I was very confused by the idea given by my professor when studying about candidate key (but i feel sham to ask him :p )
"no component of K can be eliminated without destroying
the uniqueness property --- minimality"
And i searched on wiki it says
"there is no proper subset of these attributes for which (1) holds (which means that the set is minimal)." It also give an example but i don't understand.
So my question is what does the "eliminated" here means? if it means remove the whole rows of data, then it should always keep the uniqueness of the data(because you can't lose uniqueness by removing a row of data). If it means only remove the single attribute of K and left a row with a empty "block", it looks silly and will destroy the data. So can someone give me some simple example for what does this property mean?(maybe one for the good one and one for the bad one) Thank you~
"Elimination" here does not touch the data at all. It just means that you remove one attribute/column from your key. If that reduced set of columns is still a key (i.e. uniquely identifies any data row), then the previous key was not minimal.
Example:
name id amount
A 1 1000
B 2 2000
C 3 1000
You could use name or id as a minimal key.
You could also use [name, id] as a (compound, multi-column) key. But that key is not minimal (because you can remove one column from it and still have a key).
The column amount in itself does not make a key at all.
[amount, id] would be a key, but again, it is not minimal.

Redis: Find keys matching a pattern

How I can find keys matching a pattern like this:
Eg:
I have some keys:
abc:parent1
abc:parent2
abc:parent1:child1
abc:parent2:child2
How can I find only
abc:parent1
abc:parent2
Keys is specifically noted as a command not to be run in production due to the way it works. What you need here is to create an index of your keys. Use a set for storing the key names of the pattern you want. When you add a new we key, add the name of it to the set. For example:
Set abc:parent1:child1 breakfast
Sadd abc:parent1:index abc:parent1
Then when you need the list:
Smembers abc:parent1:index
Will give you the list, without the penalties and problems associated with using the "evil" keys command. Additionally you would remove an entry with sremove on key deletion. You also get as a benefit the ability to know how many keys are in the index with a single call.
If you absolutely, positively, MUST avoid using an index use SCAN instead of keys. The only time you should even consider keys is if you are running a debug slave where the only process using it is your debugging process.
Command KEYS pattern
will help you for the same, if it is not a production environment. (Never use keys in production)
ex:
redis> MSET one 1 two 2 three 3 four 4
OK
redis> KEYS *o*
1) "two"
2) "one"
3) "four"
For your specific example, the below command will work:
redis 127.0.0.1:6379> keys *parent[0-9]
1) "abc:parent2"
2) "abc:parent1"
Here's the detailed description of the command.
Update: Though the suggestion above helps you get the desired output, the redis KEYS command is evil as the others mentioned. KEYS is blocking and can consume a lot of RAM while preparing the response.
Don't use KEYS in your regular application code. If you're looking for a way to find keys in a subset of your keyspace, consider using SCAN or sets.
Thanks The Real Bill and Itamar, I got a better understanding.

How to restrict a scan to a specific group of keys

In redis (2.8.x) I have three entity types (I define the entities).
For simplicity, let's call them organizations, departments, users.
When I run scan, it iterates on all keys in the memory, but brings only what matches the match clause.
Is there a way to restrict the scan to only a subset of key? For example search
only the users group of keys?
Each group has a different (but consistent) key name pattern (org:[id] dep:[id] user:[id])
SCAN has an optional MATCH argument that accepts a glob pattern.
You can do something like this to scan through your users objects:
SCAN 0 MATCH user:*
Edit as it is too long for a comment
Clearly scan is not a magic method, a complete cycle (until you receive "0" cursor) must go through all of your keyspace. The MATCH option does the filtering in the Redis side instead of doing it in your client.
As Itamar suggested in his comment, to be able to get the keys you need without going thorough the complete keyspace, you must index them in sets (You must also maintain it on removals).
For example, if your users keys are:
user:31 user31data
user:45 user45data
user:67 user67data
user:13 user13data
You should have a SET of user IDs:
users:IDs {31, 45, 67, 13}
To retrieve all users data, and you probably wants both the ID and the data:
sort users:IDs by nosort get # get user:*