好的,所以我有一张桌子,只是变成了一个怪物。对我们的一些客户来说,查询它已经变得非常缓慢。这是相关表格:
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。事件是从certian用户,ip,service和accountId采取的操作。此EventTime表告诉我们在什么时间发生了什么事件。今天凌晨3点和上周12点都会举办活动。我们的想法是不重复事件行。
现在,对于一些客户来说,这个EventTime表已经变得非常庞大;我们最大的是240万行并且在增长。在查看时间设置时,查询它变得极其缓慢>几天。这是我们今天正在执行的查询(注意:我在本地运行查询,以最大限度地减少网络延迟或收集者点击数据库导致的TO): / p>
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表中的一列,它告诉我们要在查询中过滤到哪个客户。在执行此查询之前,我们有TrailId列表。现在这个查询非常慢,大约需要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
)
这似乎没有做任何事情。相同的查询时间。 我认为核心问题是,这个表格非常无组织。 “时间”列具有非常具体的时间值,并且它们都没有按顺序排列。例如,客户8的收集者可能正在为2014-11-12 04:12:01.000保存EventTimes,而客户10正在保存2015-03-15 13:59:21.000。因此,查询必须在过滤之前处理和排序所有这些日期。所以索引[时间]可能根本没有效果。
任何人对如何加快速度有任何想法?
答案 0 :(得分:0)
这是您的查询:
SELECT e.TrailId, e.[NameId], e.[ResourceId], e.[AccountId], e.[ServiceId]
FROM [EventTime] et WITH (NOLOCK) INNER JOIN
[Event] e WITH (NOLOCK)
ON e.Id = et.EventId
WHERE e.TrailId IN (1, 2, 3, 4, 5) AND
e.NameId = 6 AND
et.[Time] >= '2014-10-29 00:00:00.000' AND
et.[Time] <= '2014-11-12 23:59:59.000'
ORDER BY et.[Time] ASC
此查询的最佳索引可能是:Event(NameId, TrailId)
,EventTime(EventId, Time)
。这假设结果集不是很大(数千万行),在这种情况下,需要优化摆脱order by
。
答案 1 :(得分:0)
我会抛弃ID列并使主键成为EventId和Time上的复合聚类:
CREATE TABLE [EventTime](
[EventId] [bigint] NOT NULL,
[Time] [datetime] NOT NULL,
CONSTRAINT [PK_EventTime] PRIMARY KEY CLUSTERED
(
[EventId] ASC
, [Time] ASC
)
)
CREATE NONCLUSTERED INDEX [IX_EventTime_Main] ON [EventTime]
(
[Time] ASC,
[EventId] ASC
);
检查执行计划以查看是否使用了非聚集索引并删除了不需要的索引。