使用boto提升SimpleDB查询性能

2 投票
3 回答
1774 浏览
提问于 2025-04-16 00:20

我正在尝试以以下方式使用SimpleDB。

我想在SimpleDB中随时保留48小时的数据,并根据不同的需求进行查询。每个域(domain)存储1小时的数据,所以在任何时候,SimpleDB中都有48个域。随着新数据的不断上传,我会删除最旧的域,并为每个新小时创建一个新的域。

每个域的大小大约是50MB,所有域的总大小大约是2.2GB。每个域中的数据项有以下几种属性:
标识符 - 大约50个字符长 - 每个数据项1个
时间戳 - 时间戳值 - 每个数据项1个
序列数据 - 500-1000字节的数据 - 每个数据项200个

我使用Python的boto库来上传和查询数据。每秒发送1个数据项,每个域大约有200个属性。

在这个数据的一个应用中,我需要从所有48个域中获取所有数据。查询的方式是“SELECT * FROM domain”,针对所有域。我使用8个线程来查询数据,每个线程负责几个域。
例如,域1-6由线程1负责,域7-12由线程2负责,依此类推。

获取所有数据大约需要13分钟。我使用的是boto的select方法。我需要比这更快的性能。有没有什么建议可以加快查询过程?有没有其他语言可以用来提高速度?

3 个回答

0

SBBExplorer使用多线程的BatchPutAttributes功能,能够在向亚马逊的SimpleDB上传大量数据时,实现高效的写入速度。SDB Explorer支持多个并行上传。如果你的网络带宽足够,可以通过同时运行多个BatchPutAttributes进程,充分利用这段带宽,这样可以减少处理所花费的时间。

http://www.sdbexplorer.com/

0

我和你一样遇到了同样的问题,Charlie。在分析代码后,我发现性能问题主要出在SSL上。看起来程序大部分时间和CPU的运算都花在这里了。

我听说过httplib库(boto用来处理SSL的库)有个问题,就是性能提升只有在数据包超过一定大小时才会明显,不过那是针对Python 2.5的,可能已经修复了。

5

使用更多线程

我建议你把线程和域的比例从1/6调整到接近30/1。大部分时间在从SimpleDB拉取大量数据时,都是在等待。在这种情况下,增加线程数量会大大提高你的处理速度。

SimpleDB的一个限制是查询响应的大小上限为1MB。这意味着如果你要从一个域中提取50MB的数据,至少需要进行50次选择(一次原始请求加上49次额外的请求)。这些请求必须按顺序进行,因为下一次请求需要当前响应中的NextToken。如果每次选择需要2秒以上(在处理大响应和高请求量时很常见),那么每个域就要花费2分钟。如果每个线程都必须依次遍历6个域,那就大约需要12分钟。每个域一个线程的话,时间可以轻松缩短到大约2分钟。

但你应该能做得更好。SimpleDB是为并发优化的。我建议每个域使用30个线程,让每个线程在一个小时内查询一部分数据,毕竟这是日志数据。例如:

SELECT * FROM domain WHERE timestamp between '12:00' and '12:02'

(显然,你会使用真实的时间戳值)所有30个查询可以同时发起,而不需要等待任何响应。这样你仍然需要对每个域进行至少50次查询,但你可以获得更多的并发,而不是全部按顺序进行。你需要自己测试一下,看看多少线程能给你带来最佳的处理速度。我鼓励你尝试每个域最多使用60个线程,把选择条件分解为每分钟一次。如果这样有效,你就能实现完全并行的查询,并且很可能消除了所有后续页面。如果你遇到503服务不可用的错误,就减少线程数量。

域是SimpleDB的基本扩展单位,所以你有一个方便的方法来划分数据。你只需要利用好并发。与其花13分钟,我不会惊讶如果你能在同一区域的EC2上在13秒内获取数据。但实际所需时间还会受到其他一些因素的影响。

成本问题

顺便提一下,我应该提到你所做的事情的成本,尽管你没有提到这个问题。创建域和删除域是比较耗资源的操作。通常我不会建议这么频繁地使用它们。每次操作大约会消耗25秒的资源,所以每小时创建和删除一个域,每月光是域管理就要花大约70美元。你可以在一个域中存储比你提到的50MB多得多的数据。所以你可能想等数据积累多一些再删除。如果你的查询包含时间戳(或者可以包含时间戳),那么即使域中有额外的1GB旧数据,查询性能也可能不会受到影响。无论如何,GetAttributes和PutAttributes在大域大小下都不会受到性能影响,只有那些没有很好利用选择性索引的查询才会受到影响。你需要测试你的查询来确认。这只是一个建议,我知道创建/删除在概念上更干净。

另外,一次写入200个属性是比较昂贵的,因为在资源使用公式中有一个特殊情况。写入的资源使用量与属性数量的立方成正比!公式是:

0.0000219907 + 0.0000000002 N^3

这是基础费用加上每个属性的费用,其中N是属性的数量。在你的情况下,如果你在一次请求中写入所有200个属性,资源使用费用大约是每百万项250美元(如果写入256个属性则是470美元每百万)。如果你把每个请求拆分成4个请求,每个请求50个属性,你的PutAttributes数量会增加四倍,但资源使用费用会减少到每百万项大约28美元。如果你能拆分请求,那就值得这么做。如果不能(由于请求量或应用的性质),那么从成本角度来看,SimpleDB可能会变得非常不划算。

撰写回答