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 "latency.h"
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
|
#include "cluster.h"
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -993,13 +994,22 @@ void randomkeyCommand(client *c) {
|
|||||||
void keysCommand(client *c) {
|
void keysCommand(client *c) {
|
||||||
dictEntry *de;
|
dictEntry *de;
|
||||||
sds pattern = c->argv[1]->ptr;
|
sds pattern = c->argv[1]->ptr;
|
||||||
int plen = sdslen(pattern), allkeys;
|
int plen = sdslen(pattern), allkeys, pslot = -1;
|
||||||
long numkeys = 0;
|
long numkeys = 0;
|
||||||
void *replylen = addReplyDeferredLen(c);
|
void *replylen = addReplyDeferredLen(c);
|
||||||
dbIterator *dbit = dbIteratorInit(c->db, DB_MAIN);
|
|
||||||
allkeys = (pattern[0] == '*' && plen == 1);
|
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;
|
robj keyobj;
|
||||||
while ((de = dbIteratorNext(dbit)) != NULL) {
|
while ((de = di ? dictNext(di) : dbIteratorNext(dbit)) != NULL) {
|
||||||
sds key = dictGetKey(de);
|
sds key = dictGetKey(de);
|
||||||
|
|
||||||
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
|
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
|
||||||
@ -1012,7 +1022,10 @@ void keysCommand(client *c) {
|
|||||||
if (c->flags & CLIENT_CLOSE_ASAP)
|
if (c->flags & CLIENT_CLOSE_ASAP)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dbReleaseIterator(dbit);
|
if (di)
|
||||||
|
dictReleaseIterator(di);
|
||||||
|
if (dbit)
|
||||||
|
dbReleaseIterator(dbit);
|
||||||
setDeferredArrayLen(c,replylen,numkeys);
|
setDeferredArrayLen(c,replylen,numkeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,14 @@ start_server {tags {"keyspace"}} {
|
|||||||
r dbsize
|
r dbsize
|
||||||
} {6}
|
} {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} {
|
test {DEL all keys} {
|
||||||
foreach key [r keys *] {r del $key}
|
foreach key [r keys *] {r del $key}
|
||||||
r dbsize
|
r dbsize
|
||||||
|
Loading…
x
Reference in New Issue
Block a user