加载批量数据的正确方法
Correct way to load bulk data
我正在尝试将大量数据加载到 memcachedb 中。
我正在 运行 对 MySQL 数据库进行一些查询,我想将这些查询的结果存储在 memcachedb 中以便以后访问。
目前,我只是使用简单的设置命令将结果存储在 memcachedb 中,但由于这些结果有数十亿个,在循环中一个一个地存储它们是非常低效和耗时的。所以,我想知道是否有更好的方法将数据加载到 memcachedb 中?像传统RDMS中的数据导入向导
我正在使用 pylibmc 连接到 memcachedb。
pylibmc库有set_multi
函数,一次性发送一堆命令:
mc.set_multi({
'key': 'Hello',
'another': True,
#[..]
})
这应该可以很好地工作。如果您有 十亿 个密钥,您可能希望将其分成几千个块。
如果您只是通过套接字发送命令,您可能会获得更多性能。 memcache protocol
很简单。这样做的好处是您可以添加 noreply
标志,这样服务器就不会费心发送回复了。当然,这意味着您不能进行任何错误检查,并且无论出于何种原因丢失一些密钥都可以。
这是一个简单的概念证明:
#!/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()
应该输出:
STORED
STORED
VALUE key_1 0 5
abcde
END
VALUE key_2 0 5
zxcvb
END
set
命令的格式为:
set <key> <flags> <exptime> <data_size> [noreply]\r\n
<data>\r\n
当然,这只是一个概念验证;一个稍微高级一点的例子可能是这样的:
#!/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 获取数据,请考虑使用 SQL 查询创建 set
命令!例如:
select
concat('set key_', page_id, ' 0 86400 ', length(page_title), '\r\n', page_title, '\r\n')
as cmd
from page limit 2;
不确定这是否真的更快,但我怀疑是这样。
我正在尝试将大量数据加载到 memcachedb 中。 我正在 运行 对 MySQL 数据库进行一些查询,我想将这些查询的结果存储在 memcachedb 中以便以后访问。
目前,我只是使用简单的设置命令将结果存储在 memcachedb 中,但由于这些结果有数十亿个,在循环中一个一个地存储它们是非常低效和耗时的。所以,我想知道是否有更好的方法将数据加载到 memcachedb 中?像传统RDMS中的数据导入向导
我正在使用 pylibmc 连接到 memcachedb。
pylibmc库有set_multi
函数,一次性发送一堆命令:
mc.set_multi({
'key': 'Hello',
'another': True,
#[..]
})
这应该可以很好地工作。如果您有 十亿 个密钥,您可能希望将其分成几千个块。
如果您只是通过套接字发送命令,您可能会获得更多性能。 memcache protocol
很简单。这样做的好处是您可以添加 noreply
标志,这样服务器就不会费心发送回复了。当然,这意味着您不能进行任何错误检查,并且无论出于何种原因丢失一些密钥都可以。
这是一个简单的概念证明:
#!/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()
应该输出:
STORED
STORED
VALUE key_1 0 5
abcde
END
VALUE key_2 0 5
zxcvb
END
set
命令的格式为:
set <key> <flags> <exptime> <data_size> [noreply]\r\n
<data>\r\n
当然,这只是一个概念验证;一个稍微高级一点的例子可能是这样的:
#!/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 获取数据,请考虑使用 SQL 查询创建 set
命令!例如:
select
concat('set key_', page_id, ' 0 86400 ', length(page_title), '\r\n', page_title, '\r\n')
as cmd
from page limit 2;
不确定这是否真的更快,但我怀疑是这样。