构建高容量日志记录的正确方法是什么

时间:2014-05-17 16:45:23

标签: sql logging database-performance

我需要在SQL 2012数据库中记录应用程序事件。基本的记录结构要求非常简单:

CREATE TABLE [dbo].[EventLog]
(
   [ProcessId] INT NOT NULL,
   [ApplicationId] INT NOT NULL,
   [Created] DateTime NOT NULL,
   CONSTRAINT [PK_EventLog] PRIMARY KEY CLUSTERED ([ProcessId],[ApplicaionId],[Created] ASC)
)

我遇到的问题是性能问题。每天最多可生成100万个事件,随着行数的增加,插入性能也会下降 - 直到记录器无法跟上事件的程度。

我已经将批量日志写入中间纯文本文件,然后使用与主应用程序记录器分开运行的服务处理这些文件。

我怀疑罪魁祸首可能是维持索引,我想就如何更有效/更有效地解决这个问题提出一些建议。

非常感谢任何建议。

1 个答案:

答案 0 :(得分:1)

性能问题的主要原因可能是选择形成聚簇索引的列。

在聚簇索引中,数据实际上按索引键列定义的顺序存储在索引的叶级页面中。因此,在您的表中,数据以ProcessID, ApplicationID, Created的顺序存储。

在没有看到您的数据的情况下,我会假设随着时间的推移,各种ProcessIDApplicationID都会创建日志条目。如果是这种情况,对于每个插入,SQL实际上将在日志表中间的适当位置插入每个日志条目。对于SQL Server而言,这比在表的末尾插入记录更耗时。此外,当插入的记录无法放入适当的页面时,将发生页面拆分,这将导致聚簇索引碎片化 - 这将进一步降低性能。

理想情况下,您的目标应该是拥有尽可能小的聚类键,同时也是唯一的。因此,一种方法是创建一个新的ID列作为标识,并在其上创建聚簇索引。例如:

CREATE TABLE [dbo].[EventLog]
(
  [EventLogId] INT IDENTITY(1,1),
  [ProcessId] INT NOT NULL,
  [ApplicationId] INT NOT NULL,
  [Created] DateTime NOT NULL,
  CONSTRAINT [PK_EventLog] PRIMARY KEY CLUSTERED ([EventLogId])
)