-1

我有一张 Engine 的user桌子,innoDB里面有大约百万个司机

CREATE TABLE user (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Column2` varchar(14) NOT NULL,
  `Column3` varchar(14) NOT NULL,
  `lat` double  NOT NULL,
  `lng` double  NOT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB

我有一个移动应用程序跟踪用户的位置并将其发送到服务器并保存。

现在可以确定何时上线并有数百万司机发送他们的位置......数据库将关闭或非常慢。

当普通用户使用应用程序(读/写记录)时,如何避免 Mysql 数据库性能下降

我正在考虑创建新数据库以跟踪驱动程序位置,然后我将通过 cronjob 更新主数据库,例如users每次特定时间使用 lat/lng 更新表

我这里有一些限制......在这个阶段我不能切换到no-sql数据库

4

2 回答 2

0

这里有很多东西要解开...

首先,考虑使用空间数据类型来存储纬度和经度。反过来,这将允许您使用空间索引,这些索引针对在边界框中查找人员进行了优化。

其次,如果您期望如此高的流量,您可能需要一些奇特的解决方案。

首先 - 设置一个尽可能类似于生产硬件的测试台,这样您就可以寻找瓶颈。如果您预计在 5 分钟内有 100K 插入,那么您平均每秒插入 100.000 / 5 / 60 = 333 次。但是缩放平均值通常是一个坏主意 - 您需要缩放峰值。我的经验法则是,如果平均值在 1 - 10 分钟范围内,您需要能够处理 10 次平均值,因此您需要大约 3000 次插入/秒。

我会使用负载测试工具(JMeter很棒) - 并确保瓶颈不在负载测试基础架构中,而不是在目标服务器中。计算出您的目标系统在哪个负载开始达到可接受的响应时间边界 - 对于一个简单的插入语句,我将其设置为 1 秒。如果您使用的是现代硬件,没有触发器和精心设计的表格,我希望每秒至少达到 500 次插入(我的 Macbook 接近)。

使用这个测试平台来优化你的数据库模式和索引——你可以从 MySQL 中获得很多性能!

下一步是痛苦的——你几乎无法提高 MySQL 插入的原始性能(大量内存、快速 SSD 驱动器、快速 CPU;你可以使用没有索引的临时表来获取又提高了百分之几)。如果您无法使用“vanilla” MySQL 达到您的目标性能目标,那么您现在需要寻找更奇特的解决方案。

第一个是最简单的——让你的应用程序不那么健谈。这将有助于整个解决方案的可扩展性(我假设您在应用程序和数据库之间有 Web/应用程序服务器 - 它们也需要扩展)。例如,与其发送实时更新,不如应用程序可以存储 1、5、10、60、2400 分钟的数据并将其作为批次发送。如果您有 100 万每日活跃用户,峰值为 100.000 活跃用户,那么每天扩展到 100 万个事务要比每 5 分钟扩展到 100.000 个事务要容易得多。

第二种选择是在数据库前面放置一个消息队列服务器。消息队列系统比数据库更容易扩展,但是您为架构增加了显着的额外复杂性。

第三个选项是集群。这允许负载分布在多个物理数据库服务器上——但又引入了额外的复杂性和成本。

于 2018-03-12T15:43:57.023 回答
0

每秒插入 3333 行。一定要以某种方式“批量”插入。如需更高的插入率,请参阅http://mysql.rjweb.org/doc.php/staging_table

DOUBLE对于 lat/lng 来说太过分了,而且浪费空间。表的大小可能会导致性能问题(当表变得“巨大”时)。对于定位车辆,FLOAT可能更好——2 个浮点数为 8 个字节,而 2 个双精度数为 16 个字节。分辨率为 1.7 m (5.6 ft)。参考:http: //mysql.rjweb.org/doc.php/latlng#representation_choices

另一方面,如果每个用户只有一个 lat/lng,一百万行将小于 100MB,而不是一个很大的表。

要执行哪些查询?针对一个表的一百万行可能会很昂贵。“查找 10 英里(或公里)内的所有用户”需要进行表扫描。建议查看边界框,以及几个二级索引。

更多的

更新位置的调用应该连接、更新、断开连接。这将花费几分之一秒,并且可能不会超载max_connections。该设置不应太高;它可能会招来麻烦。也设置back_log为大致相同的值。

考虑“连接池”,其细节取决于您的应用程序语言、Web 服务器、MySQL 版本等。

连同中的“边界框” WHERE,有INDEX(lat), INDEX(lng);优化器将在它们之间进行选择。

现在您的服务器中有许多 CPU 内核?将网络服务器线程的数量限制为大约两倍。这提供了另一种节流机制来避免“雷击群综合症”。

query_cache_size=0通过同时使用和来关闭查询缓存query_cache_type=0。否则,QC 会花费一些开销,而基本上不会提供任何好处。

批处理INSERTs是可行的。但是你需要批处理UPDATEs。这更棘手。通过在表中收集更新,然后执行单个多表,UPDATE从该表复制到主表中应该是实用的。这个额外的表格可以像我在“staging_table”链接中讨论的乒乓球一样工作。但是...首先让我们看看其他修复是否足够。

使用innodb_flush_log_at_trx_commit = 2. 否则,瓶颈将是记录事务。缺点(丢失 1 秒的更新)可能对您的应用程序来说不是问题——因为您很快就会获得另一个 lat/lng。

寻找附近的车辆——这甚至比边界框更好,但更复杂:http: //mysql.rjweb.org/doc.php/latlng。多久寻找“附近”。我希望不是 3333/秒;这在单个服务器中是不切实际的。(多个从站可以提供一个解决方案。)无论如何,结果集不会很快改变。

于 2018-03-11T17:05:50.310 回答