【发布时间】:2017-06-28 08:47:28
【问题描述】:
我有两个表,我们每天添加大约 100k 和 150 万个新行。这些是日志条目,在超过 99% 的情况下,我对阅读时的最后 3 个工作日感兴趣。
如果我运行一个简单的查询,例如
SELECT
0 as Id, ProcessElementName, Null as ModelPath, Status, Remark, ValidFrom, Application, JobID, JobName, CreateDate, CreatedBy, MessageType, Running, Manual, Environment, RunIdentifier, BatchJobGroup, BatchJob, IsTemp, TotalRows = COUNT(*) OVER()
FROM dbo.pclTB_ProcessElementInfo WITH (NOLOCK)
WHERE
ValidFrom > '6/26/2017 12:00:00 AM'
AND ValidFrom <= '6/26/2017 11:59:59 PM'
AND (Environment in ('---')) AND
(
Remark LIKE '%' + 'btve' + '%'
AND Application = '---'
AND (IsTemp = 0 OR IsTemp IS NULL )
AND ProcessElementName = '---'
)
ORDER BY JobID ASC
OFFSET 0 ROWS FETCH NEXT 1000 ROWS ONLY
最多可能需要 10 秒。其他查询中有一些连接,但大多数都很简单。 当我手动更新统计信息时,执行时间下降到大约 2 秒,但我确信仍有改进的空间(我知道跟踪标志 2371)。
优化表(或查询?)以获取最新行的最佳方法是什么?仅使用最近 X 天的条目创建一个新表是否有意义?
编辑: 这是用于上述查询的索引
CREATE NONCLUSTERED INDEX [IX_ProcessElementNameApplicationEnvironmentValidFrom] ON [dbo].[pclTB_ProcessElementInfo]
(
[ProcessElementName] ASC,
[Application] ASC,
[Environment] ASC,
[ValidFrom] ASC
)
INCLUDE (
[Status],
[Remark],
[JobID],
[JobName],
[CreateDate],
[CreatedBy],
[MessageType],
[Running],
[Manual],
[RunIdentifier],
[BatchJobGroup],
[BatchJob],
[IsTemp]
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
【问题讨论】:
-
您正在寻找的是分区。
-
@swift 你能告诉我们你的索引是什么样的吗?我的观点是,它们教会我们使索引尽可能具有选择性,这意味着通常索引以时间戳开头,这对于此类查询来说是最糟糕的选择。
-
Remark LIKE '%' + 'btve' + '%'和AND (IsTemp = 0 OR IsTemp IS NULL )是杀手。我建议将您的表结构更改为将IsTemp作为不可为空的列,并将 NULL 替换为 0。然后您可以使用IsTemp = 0条件创建过滤索引。 -
我会将
isTemp作为索引的第一列。正如 Evaldas 所说的,这里的杀手可能是用它来评论的。也许将此列也放入索引中,而不是将其放入包含的列中。我在这里看不到任何其他机会。 -
关于备注栏,我不确定是在 ValidFrom 之前还是之后更好。所以你可能需要尝试一下。
标签: sql sql-server query-optimization sql-optimization