【发布时间】:2015-05-17 17:20:04
【问题描述】:
好的,所以我有一张刚刚变成怪物的桌子。对于我们的一些客户来说,查询它变得异常缓慢。这是有问题的表格:
CREATE TABLE [EventTime](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[EventId] [bigint] NOT NULL,
[Time] [datetime] NOT NULL,
CONSTRAINT [PK_EventTime] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
)
CREATE NONCLUSTERED INDEX [IX_EventTime_Main] ON [EventTime]
(
[Time] ASC,
[EventId] ASC
)
它有一个指向事件表的 FK。事件是从特定用户、ip、服务和 accountId 执行的操作。这个 EventTime 表告诉我们什么事件发生在什么时间。今天的凌晨 3 点和上周的中午 12 点都可能发生事件。这个想法是不重复事件行。
现在这个 EventTime 表对于一些客户来说已经变得很庞大了;我们最大的是 240mill 行并且还在增长。当查看时间设置>几天时,查询它变得异常缓慢。这是我们今天正在执行的查询(注意:我正在本地从数据库中运行查询,以最大限度地减少网络延迟或收集器访问数据库引起的 TO):
SELECT
a.TrailId, a.[NameId], a.[ResourceId], a.[AccountId], a.[ServiceId]
FROM [EventTime] b WITH (NOLOCK) INNER JOIN [Event] a WITH (NOLOCK) ON a.Id = b.EventId
WHERE
a.TrailId IN (1, 2, 3, 4, 5) AND
a.NameId IN (6) AND
b.[Time] >= '2014-10-29 00:00:00.000' AND
b.[Time] <= '2014-11-12 23:59:59.000'
ORDER BY b.[Time] ASC
注意,trailId 是 Event 表中的一列,它告诉我们要在查询中过滤到哪些客户。在我们执行这个查询之前,我们有 TrailIds 的列表。现在这个查询很慢,执行大约需要 45 分钟。以下是我尝试过的一些查询:
SELECT
a.EventId, a.[NameId], a.[ResourceId], a.[AccountId], a.[ServiceId]
FROM [EventTime] b WITH(NOLOCK)
JOIN [Event] a WITH(NOLOCK) on a.Id = b.EventId
WHERE
b.EventId IN (SELECT Id from [Event] where TrailId IN (1, 2, 3, 4, 5) AND NameId IN (6) ) AND
b.[Time] >= '2014-08-01 00:00:00.000' AND
b.[Time] <= '2014-11-12 23:59:59.000' AND
ORDER BY b.[Time] ASC
子查询适用于小型查询,但对于较大的日期范围,性能会受到很大影响。接下来我尝试了
DECLARE @ListofIDs TABLE(Ids bigint)
INSERT INTO @ListofIDs (Ids)
SELECT Id from Event where TrailId IN (140, 629, 630, 631, 632) AND NameId IN (468)
SELECT
a.EventId, a.[NameId], a.[ResourceId], a.[AccountId], a.[ServiceId]
FROM [EventTime] b WITH(NOLOCK)
JOIN [Event] a WITH(NOLOCK) on a.Id = b.EventId
WHERE
b.EventId IN (SELECT Ids FROM @ListofIDs) AND
b.[Time] >= '2014-08-01 00:00:00.000' AND
b.[Time] <= '2014-11-12 23:59:59.000' AND
ORDER BY b.[Time] ASC
将我的子查询转换为表数组供我的主要查询参考确实有点帮助。查询大约需要 33 分钟。但是还是太慢了=/
接下来我尝试使用索引。我想我可能在一个索引中投入了太多。所以我放弃了现有的并将其分成两部分。
CREATE NONCLUSTERED INDEX [IX_EventTime_Main] ON [EventTime]
(
[Time] ASC,
)
GO
CREATE NONCLUSTERED INDEX [IX_EventTime_Event] ON [EventTime]
(
[EventId] ASC
)
这似乎没有做任何事情。相同的查询时间。 我认为核心问题是,这张表非常杂乱无章。 Time 列有非常具体的时间值,它们都不是按顺序排列的。例如,客户 8 的收集器可能正在保存 2014-11-12 04:12:01.000 的 EventTimes,而客户 10 正在保存 2015-03-15 13:59:21.000。因此,查询必须在过滤之前对所有这些日期进行处理和排序。所以索引 [Time] 可能根本没有效果。
有人对如何加快速度有任何想法吗?
【问题讨论】:
-
根据语法,我猜这是 SQL Server。
-
正确。抱歉,忘记说明了。
-
您是说事件不能有重复永远,或者它不能在特定时间段内重复。如果曾经,那么一位客户有 140 毫米的独特事件!?!哦,您可能会尝试摆脱 NOLOCK 提示。是的,我可以从这里听到“但是……”。试试看吧。
标签: sql sql-server performance large-data