Optimize KEYS when pattern includes hashtag and implies a single slot. (#12754)
in #12536 we made a similar optimization for SCAN, now that hashtags in patterns. When we can make sure all keys matching the pettern will be in the same slot, we can limit the iteration to run only one one.
This commit is contained in:
parent
35c8d616cf
commit
991aff1c0f
21
src/db.c
21
src/db.c
@ -33,6 +33,7 @@
|
||||
#include "latency.h"
|
||||
#include "script.h"
|
||||
#include "functions.h"
|
||||
#include "cluster.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
@ -993,13 +994,22 @@ void randomkeyCommand(client *c) {
|
||||
void keysCommand(client *c) {
|
||||
dictEntry *de;
|
||||
sds pattern = c->argv[1]->ptr;
|
||||
int plen = sdslen(pattern), allkeys;
|
||||
int plen = sdslen(pattern), allkeys, pslot = -1;
|
||||
long numkeys = 0;
|
||||
void *replylen = addReplyDeferredLen(c);
|
||||
dbIterator *dbit = dbIteratorInit(c->db, DB_MAIN);
|
||||
allkeys = (pattern[0] == '*' && plen == 1);
|
||||
if (!allkeys) {
|
||||
pslot = patternHashSlot(pattern, plen);
|
||||
}
|
||||
dictIterator *di = NULL;
|
||||
dbIterator *dbit = NULL;
|
||||
if (server.cluster_enabled && !allkeys && pslot != -1) {
|
||||
di = dictGetSafeIterator(c->db->dict[pslot]);
|
||||
} else {
|
||||
dbit = dbIteratorInit(c->db, DB_MAIN);
|
||||
}
|
||||
robj keyobj;
|
||||
while ((de = dbIteratorNext(dbit)) != NULL) {
|
||||
while ((de = di ? dictNext(di) : dbIteratorNext(dbit)) != NULL) {
|
||||
sds key = dictGetKey(de);
|
||||
|
||||
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
|
||||
@ -1012,7 +1022,10 @@ void keysCommand(client *c) {
|
||||
if (c->flags & CLIENT_CLOSE_ASAP)
|
||||
break;
|
||||
}
|
||||
dbReleaseIterator(dbit);
|
||||
if (di)
|
||||
dictReleaseIterator(di);
|
||||
if (dbit)
|
||||
dbReleaseIterator(dbit);
|
||||
setDeferredArrayLen(c,replylen,numkeys);
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,14 @@ start_server {tags {"keyspace"}} {
|
||||
r dbsize
|
||||
} {6}
|
||||
|
||||
test {KEYS with hashtag} {
|
||||
foreach key {"{a}x" "{a}y" "{a}z" "{b}a" "{b}b" "{b}c"} {
|
||||
r set $key hello
|
||||
}
|
||||
assert_equal [lsort [r keys "{a}*"]] [list "{a}x" "{a}y" "{a}z"]
|
||||
assert_equal [lsort [r keys "*{b}*"]] [list "{b}a" "{b}b" "{b}c"]
|
||||
}
|
||||
|
||||
test {DEL all keys} {
|
||||
foreach key [r keys *] {r del $key}
|
||||
r dbsize
|
||||
|
Loading…
x
Reference in New Issue
Block a user