我有一个parent hashmap数据结构,其字符串作为键,hashmap数据结构作为子结构(猜测child1、child2、.、childN)。每个子元素都是一个简单的键值映射,有一个数字作为键,一个字符串作为值。在伪码中:
parent['key1'] = child1; // child1 is a hash map data structure
child1[0] = 'foo';
child[1] = 'bar';
...我需要将这个数据结构实现为数据库系统中的快速查找表。让我们以Python作为参考语言。
解决方案的要求:
parent散列的估计总重量最多为500 MB。用例如下:
您会推荐内存中的键值数据存储(如Redis)还是更经典的“关系”数据库解决方案?你建议我使用哪种数据模型?
发布于 2012-10-11 00:04:58
使用红皮的示例代码,假设您已经安装了Redis (以及理想的雇工),将每个父节点保存为一个散列字段,将子元素作为序列化字符串保存,并在客户端处理序列化和反序列化:
JSON版本:
## JSON version
import json
# you could use pickle instead,
# just replace json.dumps/json.loads with pickle/unpickle
import redis
# set up the redis client
r = redis.StrictRedis(host = '', port = 6379, db = 0)
# sample parent dicts
parent0 = {'child0': {0:'a', 1:'b', 2:'c',}, 'child1':{5:'e', 6:'f', 7:'g'}}
parent1 = {'child0': {0:'h', 1:'i', 2:'j',}, 'child1':{5:'k', 6:'l', 7:'m'}}
# save the parents as hashfields, with the children as serialized strings
# bear in mind that JSON will convert the int keys to strings in the dumps() process
r.hmset('parent0', {key: json.dumps(parent0[key]) for key in parent0})
r.hmset('parent1', {key: json.dumps(parent0[key]) for key in parent1})
# Get a child dict from a parent
# say child1 of parent0
childstring = r.hget('parent0', 'child1')
childdict = json.loads(childstring)
# this could have been done in a single line...
# if you want to convert the keys back to ints:
for key in childdict.keys():
childdict[int(key)] = childdict[key]
del childdict[key]
print childdict泡菜版本:
## pickle version
# For pickle, you need a file-like object.
# StringIO is the native python one, whie cStringIO
# is the c implementation of the same.
# cStringIO is faster
# see http://docs.python.org/library/stringio.html and
# http://www.doughellmann.com/PyMOTW/StringIO/ for more information
import pickle
# Find the best implementation available on this platform
try:
from cStringIO import StringIO
except:
from StringIO import StringIO
import redis
# set up the redis client
r = redis.StrictRedis(host = '', port = 6379, db = 0)
# sample parent dicts
parent0 = {'child0': {0:'a', 1:'b', 2:'c',}, 'child1':{5:'e', 6:'f', 7:'g'}}
parent1 = {'child0': {0:'h', 1:'i', 2:'j',}, 'child1':{5:'k', 6:'l', 7:'m'}}
# define a class with a reusable StringIO object
class Pickler(object):
"""Simple helper class to use pickle with a reusable string buffer object"""
def __init__(self):
self.tmpstr = StringIO()
def __del__(self):
# close the StringIO buffer and delete it
self.tmpstr.close()
del self.tmpstr
def dump(self, obj):
"""Pickle an object and return the pickled string"""
# empty current buffer
self.tmpstr.seek(0,0)
self.tmpstr.truncate(0)
# pickle obj into the buffer
pickle.dump(obj, self.tmpstr)
# move the buffer pointer to the start
self.tmpstr.seek(0,0)
# return the pickled buffer as a string
return self.tmpstr.read()
def load(self, obj):
"""load a pickled object string and return the object"""
# empty the current buffer
self.tmpstr.seek(0,0)
self.tmpstr.truncate(0)
# load the pickled obj string into the buffer
self.tmpstr.write(obj)
# move the buffer pointer to start
self.tmpstr.seek(0,0)
# load the pickled buffer into an object
return pickle.load(self.tmpstr)
pickler = Pickler()
# save the parents as hashfields, with the children as pickled strings,
# pickled using our helper class
r.hmset('parent0', {key: pickler.dump(parent0[key]) for key in parent0})
r.hmset('parent1', {key: pickler.dump(parent1[key]) for key in parent1})
# Get a child dict from a parent
# say child1 of parent0
childstring = r.hget('parent0', 'child1')
# this could be done in a single line...
childdict = pickler.load(childstring)
# we don't need to do any str to int conversion on the keys.
print childdict发布于 2012-10-10 20:02:01
绝对要和Redis一起去。它不仅速度非常快,而且精确地处理了所需的结构:http://redis.io/commands#hash
在您的示例中,您可以避免读取整个‘子哈希’,因为客户端“从散列中提取特定值(它已经知道要使用哪个键)”。
redis> HMSET myhash field1 "Hello" field2 "World"
OK
redis> HGET myhash field1
"Hello"
redis> HGET myhash field2
"World"或者,如果你真的想要整个哈希:
redis> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
redis>当然,使用客户库可以在一个可行的对象中给出正确的结果,在您的例子中,这是一个Python字典。
发布于 2012-10-10 21:30:53
在基于哈维尔提示的快速搜索之后,我想出了一个解决方案:我可以在Redis中实现一个parent散列,其中的值字段将是子散列的字符串表示。通过这种方式,我可以快速地阅读它们,并从Python程序中对它们进行评估。
仅举一个例子,我的Redis数据结构将类似于:
//write a hash with N key-value pairs: each value is an M key-value pairs hash
redis> HMSET parent_key1 child_hash "c1k1:c1v1, c1k2:c1v2, [...], c1kM:c1vM"
OK
redis> HMSET parent_key2 child_hash "c2k1:c2v1, c2k2:c2v2, [...], c2kM:c2vM"
OK
[...]
redis> HMSET parent_keyN child_hash "cNk1:cNv1, cNk2:cNv2, [...], cNkM:cNvM"
OK
//read data
redis> HGET parent_key1 child_hash
"c1k1:c1v1, c1k2:c1v2, [...], c1kM:c1vM"然后,我的Python代码只需要使用Redis绑定来查询所需的子哈希,并返回它们的实际字符串表示;剩下要做的是将字符串表示转换为相应的字典,因此可以在方便的情况下查找。
示例代码(如这个答案中所建议的):
>>> import ast
>>> # Redis query:
>>> # 1. Setup Redis bindings
>>> # 2. Ask for value at key: parent_key1
>>> # 3. Store the value to 's' string
>>> dictionary = ast.literal_eval('{' + s + '}')
>>> d
{c1k1:c1v1, c1k2:c1v2, [...], c1kM:c1vM}希望我没有错过任何东西!
https://stackoverflow.com/questions/12827349
复制相似问题