mildrenben
mildrenben

Reputation: 3757

What is the best way to store 2d arrays in Redis?

I want to store data that looks like this:

{ 
  20160120: [
    ["slug", "title", "date"],
    ["slug", "title", "date"],
    ["slug", "title", "date"]
  ]
}

What is the best way to do this in Redis?

Upvotes: 1

Views: 1466

Answers (3)

Nick Bondarenko
Nick Bondarenko

Reputation: 6351

Each time you thinking about some complex structure in Redis you should think about right decomposition.

Entry data with LIST

If your data has regular structure (like named tuple in python) - use LIST for storing (more about this):

LPUSH entry:20160120:0 slug title date
LPUSH entry:20160120:1 slug title date
LPUSH entry:20160120:2 slug title date

This gives you

  1. The most RAM saving way to store data.
  2. The fastest iteration speed.

If your data has non regular structire - you HASH as in @h0x91B answer.

First dimension?

Yes, you can use ZSET as @h0x91B suggest, but if you have no plans to delete entries from first dimenstion you can use plain incremental key to keep max index - INCE ARRAY:20160120 1. Use it like max count pattern, becouse of in most of cases you can just read you second dimension data without actual check if this data present of not.

For example for LIST case (LUA code, there KEYS is 20160120):

  local maxCount = redis.call("GET", KEYS[1]);
  local ret = {};
  for i = 0, maxCount, 1 do
     table.insert(ret, redis.call("LRANGE", "entry:" .. KEYS[1] .. ":" .. i, 0, -1);
  end
  return ret ;

ZSET way?

This way is somekind of hardcore but allows you to store and get data in one query and keep all data in one sorted set. Also, it may be more RAM saving if you have millions of entries (too much simple keys in Redis can be a problem). So the way of ZRANGEBYLEX:

       |- key for your array
       |   |- index in first dimenstion 
       |   |   |-search pattern as first dimenstion key
       |   |   |       |-actual value
ZADD entry 0 20160120:slug
ZADD entry 0 20160120:title
ZADD entry 0 20160120:date     

And query, for example all data from index 2 and 20160120 date:

ZRANGEBYLEX entry[20160120: + 

Upvotes: 3

Itamar Haber
Itamar Haber

Reputation: 49942

An alternative approach that is sometimes suitable is to store the serialized array as a String (or perhaps as a member in another data structure if multiple such arrays exist). Keep in mind that both MessagePack and JSON have built-in support in Redis' Lua, so you can easily leverage that for targeted reads & writes.

The trade off, of course, are the compute resources needed for de/serializng.

Upvotes: 1

h0x91B
h0x91B

Reputation: 1246

Many ZSET's if you need save order in Arrays, or use SET's if order not matter.

If SET's is to big for SMEMBERS use SSCAN to iterate over whole list.

Also you can use HSET and store your array entry in this way:

HMSET HSET:ENTRY:20160120:0 "slug" "slug-data1" "title" "title-data" "date" "date-data"
HMSET HSET:ENTRY:20160120:1 "slug" "slug-data2" "title" "title-data" "date" "date-data"
HMSET HSET:ENTRY:20160120:2 "slug" "slug-data3" "title" "title-data" "date" "date-data"

ZADD ENTRY:20160120 0 HSET:ENTRY:20160120:0 1 HSET:ENTRY:20160120:1 2 HSET:ENTRY:20160120:2

My opinion - HSET+ZSET for storing order is best way (in memory keys will be optimised so no extra memory will needed)

Upvotes: 1

Related Questions