我有一个包含大约3亿行的错误日志表。 Date列上有一个索引,但我试图通过日期和错误消息进行查询。当我按日期查询时它很快但我需要按消息查询,这会减慢它的速度。
我的查询如下
WITH data_cte(errorhour, message)
AS (SELECT Datepart(hh, date) AS ErrorDay,
message
FROM cloud.errorlog
WHERE date <= '2016-06-02'
AND date >= '2016-06-01')
SELECT errorhour,
Count(*) AS count,
message
FROM data_cte
WHERE message = 'error connecting to the server'
GROUP BY errorhour
ORDER BY errorhour
添加where子句会降低速度,因为Message未编入索引。我怎样才能加快速度?
编辑:我无法在Message
上编制索引,因为它定义为varchar(max)
。
答案 0 :(得分:2)
只需为<line><e></e></line>
<line><e><e></e></e></line>
<line><e><e></e><e></e></e></line>
创建一个复合索引并过滤内部cte,而不是在外部。
(date, message)
答案 1 :(得分:1)
如果您始终正在搜索文本'error connecting to the server'
,那么您可以使用过滤的索引:
CREATE INDEX ix_ectts ON ErrorLog (Date)
WHERE (Date between '2016-06-01' and '2016-06-02')
AND Message='error connecting to the server';
此索引的字节数应相当小,并且可以快速查阅。 然而,更新可能相当慢;考虑每次需要运行此查询并在之后删除它时创建它。
另一个选择是use a computed column on the first few hundred characters of Message
, and index on that:
ALTER TABLE ErrorLog
ADD Message_index AS (cast (Message as varchar(400)));
CREATE INDEX theIndex ON ErrorLog (Message_index, [date]);
编辑:投射后添加了缺少的括号
答案 2 :(得分:0)
您可以将查询简化为:
SELECT Datepart(day, date) AS ErrorDay, datepart(hour, date) as ErrorHour
count(*)
FROM cloud.errorlog
WHERE date <= '2016-06-02' AND date >= '2016-06-01') AND
message = 'error connecting to the server'
GROUP BY Datepart(day, date), datepart(hour, date);
然后,对于此查询,您需要errorlog(message, date)
上的索引。由于相等比较,message
在索引中排在第一位是很重要的。
编辑:
如果消息太长而您想要这样的查询,我建议添加一个计算列并将其用于索引和where
子句:
alter table errlog add message250 as (left(message, 250));
create index idx_errlog_message250_date on (message250, date);
然后将查询写为:
SELECT Datepart(day, date) AS ErrorDay, datepart(hour, date) as ErrorHour
count(*)
FROM cloud.errorlog
WHERE date <= '2016-06-02' AND date >= '2016-06-01') AND
message250 = 'error connecting to the server'
GROUP BY Datepart(day, date), datepart(hour, date);
答案 3 :(得分:0)
如果可以提取错误消息的简短摘要,那么您可以在INSERT中将其包含在日志中,并将其包含在error_summary
新列中,您可以对其进行索引并在SELECT中使用它。
您解析完整的错误消息并删除时间戳,用户ID和特定内容,例如服务器名称和堆栈跟踪。如果没有明确的解析,请将error_summary
保留为null
。然后,您可以在error_summary
上进行初步搜索,如果失败则返回Message
搜索。