Performance SQLServer2008R2:大约15000个事件日志行(如何查询所有不同错误的列表?)
我有一个非常大的数据库,它存储了很多事件日志,大约1500万行。 当我尝试这个查询时,完全不可能得到一些结果 你知道我该怎么做吗?也许是索引视图 (顺便说一句:问题只是性能问题。除此之外,如果条目少得多,那么查询就正常工作了。) 各表:Performance SQLServer2008R2:大约15000个事件日志行(如何查询所有不同错误的列表?),performance,tsql,sql-server-2008-r2,query-performance,Performance,Tsql,Sql Server 2008 R2,Query Performance,我有一个非常大的数据库,它存储了很多事件日志,大约1500万行。 当我尝试这个查询时,完全不可能得到一些结果 你知道我该怎么做吗?也许是索引视图 (顺便说一句:问题只是性能问题。除此之外,如果条目少得多,那么查询就正常工作了。) 各表: CREATE TABLE [dbo].[EntryTypes] ( [pk_EntryType] [int] IDENTITY(1,1) NOT NULL, [EntryType] [nvarchar](50) NOT NULL, CO
CREATE TABLE [dbo].[EntryTypes]
(
[pk_EntryType] [int] IDENTITY(1,1) NOT NULL,
[EntryType] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_EntryTypes]
PRIMARY KEY CLUSTERED ([pk_EntryType] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[LogNames]
(
[pk_LogName] [int] IDENTITY(1,1) NOT NULL,
[LogName] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_LogNames]
PRIMARY KEY CLUSTERED ([pk_LogName] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[Sources]
(
[pk_Source] [int] IDENTITY(1,1) NOT NULL,
[Source] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Sources]
PRIMARY KEY CLUSTERED ([pk_Source] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[Servers]
(
[pk_Server] [int] NOT NULL,
[Server] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Servers]
PRIMARY KEY CLUSTERED ([pk_Server] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[Main]
(
[pk_Main] [int] IDENTITY(1,1) NOT NULL,
[Time] [datetime] NOT NULL,
[EventId] [int] NOT NULL,
[Id] [bigint] NOT NULL,
[Msg] [ntext] NOT NULL,
[Indx] [int] NOT NULL,
[fk_Server] [int] NOT NULL,
[fk_Source] [int] NOT NULL,
[fk_LogName] [int] NOT NULL,
[fk_EntryType] [int] NOT NULL,
CONSTRAINT [PK_Main]
PRIMARY KEY CLUSTERED ([pk_Main] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
CREATE TABLE [dbo].[Errors]
(
[pk_Error] [int] IDENTITY(1,1) NOT NULL,
[Time] [datetime] NOT NULL,
[ErrorMsg] [varchar](50) NOT NULL,
[ErrorMsgFull] [ntext] NOT NULL,
[fk_Server] [int] NOT NULL,
CONSTRAINT [PK_Errors]
PRIMARY KEY CLUSTERED ([pk_Error] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
ALTER TABLE [dbo].[Errors] WITH CHECK
ADD CONSTRAINT [FK_Errors_Servers]
FOREIGN KEY([fk_Server]) REFERENCES [dbo].[Servers] ([pk_Server])
ALTER TABLE [dbo].[Errors] CHECK CONSTRAINT [FK_Errors_Servers]
ALTER TABLE [dbo].[Main] WITH CHECK
ADD CONSTRAINT [FK_Main_EntryTypes]
FOREIGN KEY([fk_EntryType]) REFERENCES [dbo].[EntryTypes] ([pk_EntryType])
ALTER TABLE [dbo].[Main] CHECK CONSTRAINT [FK_Main_EntryTypes]
ALTER TABLE [dbo].[Main] WITH CHECK
ADD CONSTRAINT [FK_Main_LogNames]
FOREIGN KEY([fk_LogName]) REFERENCES [dbo].[LogNames] ([pk_LogName])
ALTER TABLE [dbo].[Main] CHECK CONSTRAINT [FK_Main_LogNames]
ALTER TABLE [dbo].[Main] WITH CHECK
ADD CONSTRAINT [FK_Main_Servers]
FOREIGN KEY([fk_Server]) REFERENCES [dbo].[Servers] ([pk_Server])
ALTER TABLE [dbo].[Main] CHECK CONSTRAINT [FK_Main_Servers]
ALTER TABLE [dbo].[Main] WITH CHECK
ADD CONSTRAINT [FK_Main_Sources]
FOREIGN KEY([fk_Source]) REFERENCES [dbo].[Sources] ([pk_Source])
ALTER TABLE [dbo].[Main] CHECK CONSTRAINT [FK_Main_Sources]
1500万排也没那么大。只需确保服务器中有良好的索引和足够的RAM即可。在这种情况下,在
Main.fk_EntryType
上添加索引可能会大大提高性能。将fk_服务器
、fk_日志名
和fk_源
以相同的顺序包含在同一索引中(以匹配查询的GROUP BY和order BY子句),也可能有所帮助
如果这些额外的表实际上都只有一列,那么首先只需将该数据存储在主表中,您可能会做得更好。这将允许索引以正确的顺序覆盖查询数据,从而为数据库节省大量重新排序结果的工作。如果不可能,则可能需要一个
最后一个选项是将
Main.Msg
ntext列移动到它自己的表中。如果您的数据库服务器内存非常有限,这将允许数据库将Main
表的其余部分保留在内存中,以便进行更快的检索,而无需添加额外的索引。1500万行并不是那么大。只需确保服务器中有良好的索引和足够的RAM即可。在这种情况下,在Main.fk_EntryType
上添加索引可能会大大提高性能。将fk_服务器
、fk_日志名
和fk_源
以相同的顺序包含在同一索引中(以匹配查询的GROUP BY和order BY子句),也可能有所帮助
如果这些额外的表实际上都只有一列,那么首先只需将该数据存储在主表中,您可能会做得更好。这将允许索引以正确的顺序覆盖查询数据,从而为数据库节省大量重新排序结果的工作。如果不可能,则可能需要一个
最后一个选项是将Main.Msg
ntext列移动到它自己的表中。如果您的数据库服务器内存非常有限,这将允许数据库将主表的其余部分保留在内存中,以便更快地检索,而无需添加额外的索引;
如果dbo中有许多行。[EntryTypes],请确保在[EntryType]上有索引(如果“错误”行少于表内容的两%并且足够多)。将其作为一个过滤索引,以获得更高的性能
尝试在联接中使用的所有列上放置非聚集索引(如果有多个列索引,则始终使用包含最多nr唯一值的列)
尝试将查询中的所有列都放在索引中,以获得覆盖索引的效果。
尝试通过和使用DISTINCT删除您的组
此外,请检查您的查询计划,查看哪些操作花费的时间最多,以及建议使用哪些新索引…首先;
如果dbo中有许多行。[EntryTypes],请确保在[EntryType]上有索引(如果“错误”行少于表内容的两%并且足够多)。将其作为一个过滤索引,以获得更高的性能
尝试在联接中使用的所有列上放置非聚集索引(如果有多个列索引,则始终使用包含最多nr唯一值的列)
尝试将查询中的所有列都放在索引中,以获得覆盖索引的效果。
尝试通过和使用DISTINCT删除您的组
另外,请检查您的查询计划,查看哪些操作花费的时间最多,以及建议使用哪些新索引…试试这个
有5个连接,我打赌它在每一个连接上循环,并执行最后一个连接的位置
您也可以在不使用GROUPBY的情况下执行SELECTDISTINCT,但它可能是相同的查询计划
并在dbo.EntryTypes.EntryType上放置一个非聚集索引
如果这不能解决问题,那么在dbo.Main.Msg上添加一个非聚集索引
我不同意Joel的观点,将Main.Msg放在一个单独的表中会有帮助
也不认为将所有这些FK添加到dbo.EntryTypes.EntryType索引会有所帮助
SELECT dbo.Main.Msg
, dbo.EntryTypes.EntryType
, dbo.EventIds.EventId
, dbo.LogNames.LogName
, dbo.Servers.Server
, dbo.Sources.Source
FROM dbo.Main
JOIN dbo.EntryTypes
ON dbo.EntryTypes.pk_EntryType = dbo.Main.fk_EntryType
AND dbo.EntryTypes.EntryType = 'Error'
JOIN dbo.EventIds
ON dbo.EventIds.pk_EventId = dbo.Main.fk_EventId
JOIN dbo.LogNames
ON dbo.LogNames.pk_LogName = dbo.Main.fk_LogName
JOIN dbo.Servers
ON dbo.Servers.pk_Server = dbo.Main.fk_Server
JOIN dbo.Sources
ON dbo.Sources.pk_Source = dbo.Main.fk_Source
GROUP BY
dbo.Main.Msg
, dbo.EntryTypes.EntryType
, dbo.EventIds.EventId
, dbo.LogNames.LogName
, dbo.Servers.Server
, dbo.Sources.Source
ORDER BY ...
为什么在所有这些[nvarchar](50)
上没有独特的约束
这很奇怪。使用这种设计,a可能会有重复的消息创建唯一的行,但您没有报告[pk_Main]。试试这个
有5个连接,我打赌它在每一个连接上循环,并执行最后一个连接的位置
您也可以在不使用GROUPBY的情况下执行SELECTDISTINCT,但它可能是相同的查询计划
并在dbo.EntryTypes.EntryType上放置一个非聚集索引
如果这不能解决问题,那么在dbo.Main.Msg上添加一个非聚集索引
我不同意Joel的观点,将Main.Msg放在一个单独的表中会有帮助
也不认为将所有这些FK添加到dbo.EntryTypes.EntryType索引会有所帮助
SELECT dbo.Main.Msg
, dbo.EntryTypes.EntryType
, dbo.EventIds.EventId
, dbo.LogNames.LogName
, dbo.Servers.Server
, dbo.Sources.Source
FROM dbo.Main
JOIN dbo.EntryTypes
ON dbo.EntryTypes.pk_EntryType = dbo.Main.fk_EntryType
AND dbo.EntryTypes.EntryType = 'Error'
JOIN dbo.EventIds
ON dbo.EventIds.pk_EventId = dbo.Main.fk_EventId
JOIN dbo.LogNames
ON dbo.LogNames.pk_LogName = dbo.Main.fk_LogName
JOIN dbo.Servers
ON dbo.Servers.pk_Server = dbo.Main.fk_Server
JOIN dbo.Sources
ON dbo.Sources.pk_Source = dbo.Main.fk_Source
GROUP BY
dbo.Main.Msg
, dbo.EntryTypes.EntryType
, dbo.EventIds.EventId
, dbo.LogNames.LogName
, dbo.Servers.Server
, dbo.Sources.Source
ORDER BY ...
为什么在所有这些[nvarchar](50)
上没有独特的约束
这很奇怪。使用这种设计,a可以使用重复的消息创建唯一的行,但您没有报告[pk_Main]。为什么需要分组依据
?否则我会得到双倍。有很多相同的事件。据我所知,你有一个大约15000000行的表。您正在对表执行一个到一组引用表的连接,然后根据表上的主id进行聚合。即使查询确实返回了结果,读取15000000行也可能需要一些时间。也许你应该问另一个问题,包括样本数据和期望的结果