son*_*ard 10 performance database-design sql-server vldb
我们以大约 5000 pr 的速率接收实时 GPS 数据。分钟(来自 4 个 TCP 服务器)。每个服务器使用单个连接来插入数据,并在插入之间缓冲数据。每隔 15 分钟左右,服务就会获取这些数据,并将其处理为行程。一旦生成了行程,实际的 GPS 数据通常就不那么重要了,只有当用户想在地图上查看路线时才会如此。
问题是数据库似乎正在努力跟上插入数据的速度。有时,当负载增加时,插入时间突然急剧增加(> 30 秒),这反过来又允许缓冲更多数据,从而导致更大的插入和更长的插入持续时间。
我希望得到一些关于当前设计的评论,一些我们必须提高性能的想法,以及我们一些问题的答案 - 以及人们可能有的任何其他提示!
当前设计
数据目前被分成代表一周的表格,并且超过一年的数据被存档到辅助数据库中。整个事情在一个可编辑的视图中连接在一起,用于插入和读取。
餐桌设计
指数
目前每周大约占用 10 GB 包括索引,目前主数据库中有大约 300 GB 数据。
主数据库中的数据表有自己的包含 1 个文件的文件组,但它与主数据库中的所有其他表在同一磁盘上。辅助数据库在不同的磁盘上,但在同一台机器上。
我认为我们也每周运行一次索引重建作业,当一个新的表分区(周)被使用时。不执行收缩。
该机器是具有 12 GB 内存的 8 核 HP,保存主数据库的磁盘运行 RAID 10。
想法
如果需要更多信息,请告诉我。影响性能的因素有很多,而且调整它的方法可能也有很多。
每分钟 5000 次插入大约是每秒 83 次插入。有 5 个索引,每秒插入 400 个物理行。如果工作负载在内存中,即使是最小的服务器也不会有问题。即使这是使用我能想到的最低效的方式逐行插入。从 CPU 的角度来看,每秒 83 次琐碎的查询并不有趣。
可能,您受磁盘限制。您可以通过查看等待统计信息或STATISTICS IO
.
您的查询可能涉及许多不同的页面,因此缓冲池没有空间容纳所有页面。这会导致频繁的页面读取和可能的随机磁盘写入。
想象一个表,由于不断增加的键,您只能在最后进行物理插入。工作集将是一页:最后一页。这也会在惰性写入器或检查点进程将表的“结尾”写入磁盘时生成顺序 IO。
想象一个带有随机放置插入的表(经典示例:guid 键)。在这里,所有页面都是工作集,因为每个插入都会触及随机页面。IO 是随机的。这是工作集最糟糕的情况。
你在中间。你的索引是结构(SomeValue, SequentialDateTime)
。第一个组件部分随机化第二个组件提供的顺序。我猜“ SomeValue
”有很多可能的值,因此您的索引中有许多随机放置的插入点。
您说每周将数据拆分为 10GB 的表。这是一个很好的起点,因为工作集现在以 10GB 为界(不考虑您可能执行的任何读取操作)。但是,对于 12GB 的服务器内存,所有相关页面都不太可能保留在内存中。
如果您可以减少每周“分区”的大小或稍微增加服务器内存,那么您可能没问题。
我希望在一周开始时插入比在结束时更快。您可以在开发服务器上通过运行具有特定数据大小的基准测试并逐渐减少服务器内存来测试该理论,直到您看到性能下降。
现在,即使所有读取和写入都适合内存,您可能仍然有随机脏页刷新 IO。摆脱这种情况的唯一方法是写入索引中的同一位置。如果您完全可以将索引转换为使用(更多)顺序键,那将有很大帮助。
作为一个快速的解决方案,我会在客户端和主表之间添加一个缓冲层。可能累积 15 分钟的写入到临时表并定期刷新它。这消除了负载峰值并使用更有效的计划来写入大表。