我正在寻找一些帮助。我有一个针对相当大的表(200 万条记录)运行的查询。
我一直在努力让索引有效地工作。还有一些针对此表的其他查询,但这是迄今为止最常见的查询。我很难让它在 1 秒内执行,并且经常看到它使用分析器在 3 到 5 秒内运行。
它可能会尽可能快,但我希望得到一些输入来确认/拒绝。
请注意:开发人员根本不会更改查询或架构。只能在数据库中进行优化,不能更改架构。
桌子:
CREATE TABLE [dbo].[Notifications](
[ntID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[NotificationID] [int] NOT NULL,
[NotificationType] [nvarchar](50) NOT NULL,
[UserName] [nvarchar](50) NULL,
[CreatedBy] [nvarchar](50) NULL,
[CreatedOn] [datetime] NULL,
[Status] [nvarchar](50) NOT NULL,
[Result] [nvarchar](50) NULL,
[Extension] [nvarchar](50) NULL,
[ShiftRate] [nvarchar](255) NULL,
[ResponseMinutes] [int] NULL,
[ResponseWindow] [datetime] NULL,
[caNotificationID] [int] NULL,
[AwardedBy] [nvarchar](50) NULL,
[AwardedOn] [datetime] NULL,
[CancelledBy] [nvarchar](50) NULL,
[CancelledOn] [datetime] NULL,
[CancelledReasonID] [int] NULL,
[CancelledReasonText] [nvarchar](255) NULL, …
Run Code Online (Sandbox Code Playgroud) index sql-server index-tuning nonclustered-index sql-server-2016
我正在创建一个数据仓库。我以 5 分钟的间隔创建了一个时间维度 (Dim_Time)。小时聚合将具有 [分钟] = NULL。出于本示例的目的:
CREATE TABLE [dbo].[Dim_Time](
[TimeID] [int] IDENTITY(1,1) NOT NULL,
[StartDateTime] [datetime] NULL,
[Hour] [int] NULL,
[Minute] [int] NULL,
CONSTRAINT [PK_Dim_Time] PRIMARY KEY CLUSTERED
([TimeID] ASC)
) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
然后我有一个传入表,它每 5 分钟从 OLTP 数据库更新一次。
CREATE TABLE [dbo].[Stg_IncomingQueue](
[IncomingID] [int] IDENTITY(1,1) NOT NULL,
[CustomerID] [int] NOT NULL,
[TimeID] [int] NULL,
[InsertTime] [datetime] NULL,
CONSTRAINT [PK_IncomingQueueMonitor] PRIMARY KEY CLUSTERED
([IncomingID] ASC)
) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
然后我有以下 While 循环。其目的是获得与特定传入行相关的正确 5 分钟时隙 (TimeID):
WHILE 0 < (SELECT COUNT(*) …
Run Code Online (Sandbox Code Playgroud) 我希望你们能在这里帮助我。我们的应用程序每 3 秒轮询一次消息表,寻找要发送的通知。这适用于我们所有的客户(单租户数据库),除了一个。他们将一天 23 小时没有活动,然后一次加载数千条消息(3000+)。在其他情况下,这个卷什么都不是,我们可以轻松处理它,除了在这种情况下,下面的 SQL 查询需要大约 30 秒才能运行,并且随着队列在更新时备份而变得更糟,需要排他锁和因此阻止所有其他查询,因此问题会导致各种破坏。这都是由于糟糕的查询计划造成的。
我们每天早上 5 点进行每日重新索引(重组 < 30%,重建 > 30%,忽略 <5%)以及更新统计信息。这些都来自 Ola Hallengren 维护解决方案。我们也在 SQL Server 2016 上并且完全是最新的 (13.0.5492.2)
我手头没有这 2 个计划,但基本上坏计划会执行 MessagesSent 表(3.5m 行)的全表扫描。
我的理论是,由于查询一整天都没有返回任何内容,因此某些部分没有执行,因此错误查询是最有效的 SQL 查询。
这将在刷新查询计划后继续,因为它只生成相同的计划,但是当我在 MessagesSent 表上更新统计信息时,创建好的计划并且一切正常,查询在大约 10-30 毫秒内执行。
有谁知道我如何微调它以始终使用更好的计划,即使查询返回的数据不存在?作为修补程序,我们向应用程序添加了重新编译选项,但我认为这不是每 3 秒执行一次的查询的理想解决方案。
这是查询:
WITH TopMessage
AS
(
SELECT TOP 1 ID, BatchID FROM MessagesSent
JOIN Units ON Unit = idUnit
WHERE MessageDate <= GETDATE()
AND Active = 'True'
AND Status = 'Queued'
AND NOT(DialString = 'null')
AND Unit = ('29') …
Run Code Online (Sandbox Code Playgroud)