Более быстрый способ перебора всех ключей и значений в Redis DB - PullRequest
0 голосов
/ 23 мая 2018

У меня есть БД с около 350 000 ключей.В настоящее время мой код просто перебирает все ключи и получает свое значение из базы данных.

Однако это занимает почти 2 минуты, что кажется очень медленным, redis-benchmark дало 100 тыс. Запросов / 3 с.

Я посмотрел на конвейерную обработку, но мне нужно, чтобы каждое возвращаемое значение получалось, чтобы в итоге я получил набор ключей, пар значений.

В настоящий момент я думаю об использовании потоков в моем коде, если это возможно, для ускоренияэто лучший способ справиться с этим вариантом использования?

Вот код, который у меня есть.

import redis, timeit
start_time = timeit.default_timer()
count = redis.Redis(host='127.0.0.1', port=6379, db=9)
keys = count.keys()

data = {}

for key in keys:
    value = count.get(key)
    if value:
        data[key.decode('utf-8')] = int(value.decode('utf-8'))

elapsed = timeit.default_timer() - start_time

print('Time to read {} records: '.format(len(keys)), elapsed)

1 Ответ

0 голосов
/ 23 мая 2018

Во-первых, самый быстрый способ сделать все это внутри EVAL .

Далее, рекомендуемый подход для итерации всех ключей: SCAN .Он не будет повторяться быстрее, чем KEYS, но позволит Redis обрабатывать некоторые другие промежуточные действия, поэтому он поможет с общим поведением приложения.

Сценарий будет выглядеть как local data={} local i=1 local mykeys=redis.call(\"KEYS\",\"*\") for k=1,#mykeys do local tmpkey=mykeys[k] data[i]={tmpkey,redis.call(\"GET\",tmpkey)} i=i+1 end return data, но он будетпотерпеть неудачу, если у вас есть ключи, недоступные с помощью GET (например, наборы, списки).Вам нужно добавить обработку ошибок к нему.Если вам нужна сортировка, вы можете сделать это либо непосредственно в LUA, либо позже на стороне клиента.Второй будет медленнее, но не позволит другим пользователям экземпляра redis ждать.

Пример вывода:

127.0.0.1:6370> eval "local data={} local i=1 local mykeys=redis.call(\"KEYS\",\"*\") for k=1,#mykeys do local tmpkey=mykeys[k] data[i]={tmpkey,redis.call(\"GET\",tmpkey)} i=i+1 end return data" 0
1) 1) "a"
   2) "aval"
2) 1) "b"
   2) "bval"
3) 1) "c"
   2) "cval"
4) 1) "d"
   2) "dval"
5) 1) "e"
   2) "eval"
6) 1) "f"
   2) "fval"
7) 1) "g"
   2) "gval"
8) 1) "h"
   2) "hval"
...