目前我有一个系统(服务器),它一次接收来自 1000 个设备(客户端)的消息,每个设备每分钟发送一次消息。
每条消息将有超过 2000 条记录。
所以每分钟系统将收到 1000 X 2000 => 2,000,000 条记录
同时我期待频繁的选择请求(大约 1000 个)
查询是
设置数据库服务器(Mysql/postgres)来处理这种频繁的批量插入和读取操作的最佳方法是什么?
目前我有一个系统(服务器),它一次接收来自 1000 个设备(客户端)的消息,每个设备每分钟发送一次消息。
每条消息将有超过 2000 条记录。
所以每分钟系统将收到 1000 X 2000 => 2,000,000 条记录
同时我期待频繁的选择请求(大约 1000 个)
查询是
设置数据库服务器(Mysql/postgres)来处理这种频繁的批量插入和读取操作的最佳方法是什么?
所以我只是批处理了 1M 假行(一个字符和一个从 1 到 1000000 的整数)并将其插入到我笔记本电脑上 postgresql 的一个事务中。花了4秒。一分钟插入 100 万次很容易,至少一开始是这样。然而,还有很多事情需要担心。例如,更新索引可能会很昂贵。我在整数字段上添加了唯一索引,插入时间从 4 秒变为 9 秒。插入另外 1M 行需要 14 秒。随着指数的增长,这个数字将继续攀升。一旦索引不再适合内存,它就会飙升。
通常,处理这么多数据的最佳方法是将其填充到离散的文本文件中,并在以后批量上传而无需索引。然后添加索引。
Ollie 在他关于 MySQL 的回答中提到的所有内容也适用于大多数其他数据库。
PostgreSQL特定的东西:
使用连接池和持久连接,将总连接数保持在较低水平,例如低于 100。
使用 FAST 存储介质。您在这里遇到的问题是您可能需要大量存储空间,因此 SSD 可能无法工作。如果您必须使用旋转驱动器,请将它们中的很多放在 RAID 控制器下,并在 RAID-10 中使用电池支持的硬件缓存,以获得最佳性能和良好的可靠性。RAID-5 或 6 在这里将是一场灾难,因为它们的写入性能很糟糕。
尽可能将尽可能多的写入批处理。与一些会在大事务上呕吐的数据库不同,PostgreSQL 在一个事务中一次处理 1M 或更多行非常舒服。
根据需要使用尽可能少的索引。
你的一千台设备是如何连接的?如果每个人都与您的服务器建立 TCP/IP 连接,您需要确保在他们连接的机器中有足够的文件描述符。查看/proc/sys/fs/file-max
最大值。与单个服务器计算机的一千个客户端连接被认为是一个很大的数字。
每条记录有多少数据?你会让你的网络硬件不堪重负吗?如果每条记录是十个字节,那么您说的是每秒输入两千万字节,或一亿六千万位。每秒 100 兆位的以太网接口是远远不够的。即使是千兆接口也是有问题的:很难保持巨大的吞吐量。请记住,如果 DBMS 与接收数据的服务器位于不同的机器上,则这些记录将不得不进出,使您的网络吞吐量翻倍。
您将如何处理您的 DBMS 或系统的某些其他部分将落后于其工作负载的可能性?DBMS 在接受 INSERT 命令时偶尔会延迟 30 秒是很可能的,但在此期间会积累大量未处理的数据。
您应该考虑将此问题划分为可能包含 50 或 100 个设备的组,以及 20 或 10 个收集数据的中央服务器设置。如果您这样做,您将不会出现单点故障,您不会非常努力地推动您的网络硬件,并且如果您丢失一些硬件,您可能能够制定某种故障转移策略。您还可以使用更便宜、更具成本效益的服务器和网络设备。
在 MySQL 上,使用尽可能少的索引来支持您需要执行的查询。请记住,执行摘要查询(如SELECT COUNT(*) FROM raw WHERE timestamp > NOW() - INTERVAL 1 HOUR
)会在运行时显着减慢 INSERT 操作。
您可能需要考虑使用诸如 ActiveMQ 之类的排队系统来处理您的数据流。
您通常可以针对写入或读取进行优化,但不能同时针对两者进行优化。因此,在这种情况下,仔细修剪表的大小,只声明所需的索引,并将其放在快速的机器上,可能是您唯一的选择。您是否需要长时间保留数据,或者您可以清除旧数据?否则你的桌子会变得非常大。