我如何使用DynamoDB将此用法从我的mysql db移动到nosql?

时间:2016-07-16 10:22:39

标签: mysql amazon-web-services amazon-dynamodb amazon-rds nosql

我目前遇到的问题是我开发的服务严重依赖于db(500行)的大量有效负载读取。我看到了巨大的吞吐量,每分钟35,000多个请求,每个请求通过数据库最多500行,而且根本没有处理扩展。

主要在纬度/经度上检索有问题的数据,其中检查行的纬度和经度是否可以包含在最小纬度经度坐标和最大纬度经度坐标内。这有效地检查有问题的行是否在最小/最大传递到where的位置创建的边界框内。

这是我们依赖的查询的哪个部分供参考。

s.latitude > {minimumLatitude} AND 
s.longitude > {minimumLongitude} AND 
s.latitude < {maximumLatitude} AND 
s.longitude < {maximumLongitude}
是的,那就是说。 MySQL正在处理这个发现,我目前在RDS上并且不得不严重依赖r3.8XL主机,并且3 r3.8XL读取只是为了获得我需要的吞吐量容量以防止应用程序减速并将C​​PU投入100%使用率。

显然,有效载荷有多重以及查询的频率,这些数据需要转移到更合适的服务中。像Elasticache的服务或DynamoDB之类的东西。

我一直倾向于使用DynamoDB,但我在这里的唯一选择似乎是使用SCAN,因为没有有用的主键我可以关联我的数据以减少结果集,因为它依赖于计算纬度/经度是否为一个点在边界框内。关于属性的DynamoDB过滤器可以很好地工作,因为它们支持所需的基本条件,但是在一个250,000+行的表上,每天增加近200,000或更多将是非常昂贵的。

减少结果集的另一个选项是使用地图分级技术将地图区域与数据相关联,并将发电机中的数据减少为主键,然后进一步过滤纬度/经度属性。这不是理想的,我们更喜欢在特定范围内获取数据并且没有多余的冗余数据传回,因为最小/最大lat / lng可以重叠多个bin,然后从多数可能没有的引脚中提取数据需要。

此时我不断部署只读副本以保持服务,这绝对不是理想的。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

你似乎忽视了看起来似乎首先尝试的东西......使用适合数据性质的索引结构索引数据......在MySQL中。

B树的帮助有限,因为在另一个维度中删除不可能的匹配后,您仍需要检查所有可能的匹配。

除此之外:假设您已经有一个索引(纬度,长度),您可能会通过添加第二索引并反转列来获得一些短期性能提升(长, LAT)。在你的一个副本上尝试这个¹,看看它是否有帮助。如果你根本没有索引,那么这当然是你的第一个问题。

现在,实际的解决方案。这需要MySQL 5.7,因为在此之前,该功能适用​​于MyISAM,但不适用于InnoDB。如果您尝试使用MyISAM,RDS根本不喜欢它。

  

这是有效的检查相关行是否在最小/最大传递到where的位置创建的边界框内。

您需要的是R-Tree index。这些索引实际上以一个顺序存储点(或线,多边形等),这些顺序理解并保留它们在多个维度上的接近度...近点在索引中更接近,最小边界矩形(“边界框”)是轻松快速地确定。

MySQL spatial extensions支持此类索引。

甚至有一个MBRContains()函数可以将索引中的点与查询中的点进行比较,使用R-Tree查找您正在搜索的thr MBR中包含的所有点。与通常的优化规则不同,你不应该在where子句中使用列名作为函数参数来避免触发表扫描,这个函数是一个例外 - 优化器实际上并没有针对每一行计算函数,而是使用了表达式以对照索引进行评估。

为了理解空间扩展的设计需要一些学习曲线,但是一旦理解了原理,它就会很好地落实到位,并且性能将超出您的期望。您需要一个GEOMETRY类型的列,并且您希望将lat和long存储在一个索引列中作为POINT

要在不中断的情况下安全地测试它,请制作副本,然后将其从主服务器中分离,将其升级为自己的独立主服务器,并在必要时将其升级到5.7。创建一个具有相同结构的新表以及GEOMETRY列和SPATIAL KEY,然后使用INSERT ... SELECT填充该表。

请注意,DynamoDB scan是一项非常“昂贵”的操作。在我昨天测试的桌面上,无论记录数量多少,每次扫描时一次扫描始终要花费112个读取单位,大概是因为扫描总是读取1MB数据,这是256块4K(定义为读取单元)但不具有很强的一致性(因此,成本的一半)。 1 MB÷4KB÷2 = 128我认为它足够接近112,这就解释了这个数字。

¹即使在RDS中,向MySQL副本而不是主副本添加索引也是一种有效的受支持操作。您需要通过创建与现有参数组相同的新参数组临时使副本可写,然后在该组中将read_only翻转为0。将副本关联到新参数组,然后等待状态从应用更改为同步,登录到副本并添加索引。完成后再将参数组放回去。