首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加载大容量数据的正确方法

加载大容量数据的正确方法
EN

Stack Overflow用户
提问于 2016-02-29 07:29:31
回答 1查看 568关注 0票数 4

我正试图将大量的数据加载到memcachedb中。我正在MySQL数据库上运行一些查询,我希望将这些查询的结果存储在memcachedb中,以便以后更容易访问。

目前,我只是使用简单的set命令来将结果存储在memcachedb中,但是由于有数十亿这样的结果,将它们一个一个地存储在一个循环中是非常低效和耗时的。所以,我想知道是否有更好的方法将数据加载到memcachedb中?类似于传统RDMS中的数据导入向导。

我正在使用pylibmc连接到memcachedb。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-03 22:26:04

pylibmc库具有set_multi函数,它一次性发送一系列命令:

代码语言:javascript
复制
mc.set_multi({
    'key': 'Hello',
    'another': True,
    #[..]
})

这应该足够有效了。如果你有数十亿的钥匙,你可能想把它分成几千块。

如果您只需通过套接字发送命令,您可能会获得更高的性能。模缓存协议非常简单。这样做的好处是您可以添加noreply标志,因此服务器不会麻烦地发送回复。当然,这意味着您不能进行任何错误检查,并且由于任何原因丢失几个键是可以的。

这里有一个概念的简单证明:

代码语言:javascript
复制
#!/usr/bin/env python

import socket

data = 'set key_1 0 86400 5\r\nabcde\r\n'
data += 'set key_2 0 86400 5\r\nzxcvb\r\n'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 11211))
s.sendall(data)
print(s.recv(8192))
s.close()

# Verify if it worked!
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 11211))
s.sendall('get key_1\r\n')
s.sendall('get key_2\r\n')
print(s.recv(8192))
s.close()

哪一项应产出:

代码语言:javascript
复制
STORED
STORED

VALUE key_1 0 5
abcde
END
VALUE key_2 0 5
zxcvb
END

set命令的格式是:

代码语言:javascript
复制
set <key> <flags> <exptime> <data_size> [noreply]\r\n
<data>\r\n

当然,这只是一个概念的证明;一个稍微高级的例子可能是这样的:

代码语言:javascript
复制
#!/usr/bin/env python

import socket

def make_set(n, data):
    return 'set key_{} 0 86400 {}\r\n{}\r\n'.format(n, len(data), data)

data = open('/etc/aliases').readlines()
commands = [ make_set(n, d.strip()) for n, d in enumerate(data) if d.strip() != '' ]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 11211))
s.sendall(''.join(commands))
print(s.recv(65000))

# Verify if it worked!
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 11211))
for n in range(0, len(commands)):
    s.sendall('get key_{}\r\n'.format(n))
print(s.recv(65000))
s.close()

如果从MySQL获取数据,那么考虑使用set查询生成一个set命令!例如:

代码语言:javascript
复制
select
    concat('set key_', page_id, ' 0 86400 ', length(page_title), '\r\n', page_title, '\r\n')
    as cmd
from page limit 2;

不确定这是不是真的更快,但我怀疑是这样的。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35694060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档