具有大量插入的Web应用程序的性能

时间:2008-11-24 16:02:16

标签: database performance filesystems

对于在网站上记录用户行为并且所有流量将导致IO写入的高流量Web应用程序,最佳IO策略是什么?是写入文件并在一夜之间对数据库进行批量插入吗?或者只是为每个请求执行INSERT(或INSERT DELAYED)?我理解为了正确地考虑这个问题,需要更多关于架构的细节,但是在正确的方向上的推动将非常受欢迎。

11 个答案:

答案 0 :(得分:1)

通过写入数据库,您允许RDBMS决定何时应该发生磁盘IO - 例如,如果您有足够的RAM,它可以有效地缓存内存中的所有插入,在负载较轻时将它们写入磁盘,或其他一些调度机制。

直接写入文件系统将比带宽限制更多 - 因此写入DB然后写入,明确是因为DB理论上可以更有效的大小,连续和“方便”时间写入。

答案 1 :(得分:1)

我在最近的应用中做到了这一点。插入物通常非常便宜(特别是如果你将它们放入未加索引的漏斗表中)。我认为你有几个选择。

  1. 如上所述,将数据写入漏斗表,如果应用程序框架支持批量插入,那么使用这些,将加速它。然后每个x请求,合并(通过SP调用)到主表,在那里您可以规范化具有低熵的数据。例如,如果您正在存储请求的HTTP类型(get / post / etc),那么这只能是几种类型,最好存储为Int,并获得改进的I / O +查询性能。您的主表也可以像平常一样编制索引。

  2. 如果这还不够好,那么你可以将请求流式传输到本地文件系统上的文件,然后进行带外(即从网络服务器分离的进程)吸取这些文件并将它们BCP进入数据库。这将以更多移动部件为代价,并且可能会在接收请求和进入数据库之间产生更大的延迟

  3. 希望这有帮助,Ace

答案 2 :(得分:1)

使用RDBMS时,最重要的是优化磁盘写入操作。某些东西必须刷新()到持久存储(磁盘驱动器)才能完成每个事务,这非常昂贵且耗时。最大限度地减少事务数量并最大化写入顺序页面的数量是性能的关键。

如果您正在进行插入,在单个事务中批量发送它们将导致更有效的磁盘写入行为,从而减少刷新操作的数量。

我的建议是对消息进行排队并定期..假设每15秒左右开始一次事务...发送所有排队的插入...提交事务。

如果您的数据库支持在单个请求/命令中发送多个日志条目,那么当应用程序和RDBMS之间存在一些网络延迟时,通过减少往返次数会对性能产生显着影响。

某些系统支持批量操作(BCP),为批量加载数据提供了一种非常有效的方法,这种方法比使用“插入”查询更快。

节省使用索引和选择顺序主键有助于。

确保多个实例协调写入操作或写入单独的表可以通过减少数据库中的并发管理开销来提高某些情况下的吞吐量。

答案 3 :(得分:0)

写入文件,然后再加载。耦合到文件系统而不是数据库更安全。而且数据库比文件系统更容易失败。

答案 4 :(得分:0)

我的直觉是只使用数据库,不惜一切代价避免使用直接文件系统IO。如果你需要生成一些文件系统工件,那么我会使用夜间cron作业(或类似的东西)来读取DB记录并写入文件系统。

另请注意:只有在服务器崩溃或重新启动时不介意丢失一些记录的情况下才使用“INSERT DELAYED”,因为某些记录几乎肯定会丢失。

答案 5 :(得分:0)

使用文件系统备份写入的唯一问题是如何扩展日志。

执行不佳的记录器必须打开整个文件才能在其末尾添加一行。我目睹了一个这样的示例案例,其中人以相反的顺序登录到文件,是最新的条目首先出现,这需要将整个文件加载到内存中,将1行写入新文件,然后写入原始文件之后的内容。

此日志最终超过了phps内存限制,因此,瓶颈了整个项目。

但是,如果你正确地执行它,文件系统读/写将直接进入系统缓存,并且每10秒或更长时间只刷新到磁盘(取决于FS / OS设置),其性能可以忽略不计与写入任意内存地址相比。

哦,是的,无论你使用什么系统,你都需要考虑并发日志追加。如果使用数据库,高插入负载可能会导致死锁条件,并且对文件,您需要确保不会有2个并发写入相互取消。

答案 6 :(得分:0)

插入通常会影响表的(读取/更新)性能。也许您可以对另一个表(或数据库)执行写操作,并具有处理此数据的批处理作业。数据库方法的优点是您可以查询/报告数据,并且所有数据在逻辑上都位于关系数据库中,并且可以更容易使用。根据数据记录到文本文件的方式,您可以开辟更多腐败的可能性。

答案 7 :(得分:0)

有一种更简单的方法来回答这个问题。描述两种解决方案的性能。

创建一个执行数据库插入的页面,另一个写入文件的页面,另一个不执行任何操作。否则,页面应该相同。使用负载测试器(例如JMeter)命中每个页面,看看性能影响是什么。

如果您不喜欢性能数字,可以轻松调整每个页面以尝试优化性能或尝试新的解决方案......从使用MSSQL支持的MSMQ延迟插入到共享日志到单个文件DB后台工作者。

这将为您做出决定提供坚实的基础,而不是依赖于其他人的推测。事实证明,所提议的解决方案都不可行,或者所有解决方案都是可行的......

答案 8 :(得分:0)

Hello from left field,但是没有人问过(你没有说明)你永远不会丢失数据有多重要?

如果速度是问题,请将其全部保留在内存中,并批量转储到数据库中。

答案 9 :(得分:0)

您是否记录的内容超过了网络服务器日志中的可用内容?它可能非常多,例如见Apache 2.0 log information

如果没有,那么你可以使用旧的缓冲技术然后批量写入。您可以在不同的位置缓冲:在服务器的内存中,然后将它们批量插入db或批量写入每个X请求的文件中,和/或每隔X秒。

如果您使用MySQL,有几种不同的选项/技术可以高效地加载大量数据:LOAD DATA INFILEINSERT DELAYED等等。

关于insertion speeds的大量细节。

其他一些提示包括:

  • 每个时间段(即:每天或每周)将数据分成不同的表格
  • 使用多个数据库连接
  • 使用多个数据库服务器
  • 拥有良好的硬件(SSD /多核)

根据可用的规模和资源,可以采用不同的方式。因此,如果您提供更多详细信息,我可以提供更具体的建议。

答案 10 :(得分:0)

如果您不需要等待生成的ID等响应,则可能需要使用消息队列或线程管理器来采用异步策略。