【发布时间】:2021-04-12 10:53:40
【问题描述】:
这是我的场景:
CREATE TABLE [dbo].[tblSMSSendQueueMain](
[ID] [int] IDENTITY(1,1) NOT NULL,
[SendMethod] [int] NOT NULL
CONSTRAINT [PK_tblSMSSendQueueLog] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[tblSMSSendQueueMainSendStatus](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[QueueID] [int] NULL,
[SendStatus] [int] NULL,
[StatusDate] [datetime] NULL,
[UserID] [int] NULL,
CONSTRAINT [PK_tblSMSSendQueueMainSendStatus] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
还有一些索引:
CREATE NONCLUSTERED INDEX [IX_tblSMSSendQueueMainSendStatus_SendStatus_Single] ON [dbo].[tblSMSSendQueueMainSendStatus]
(
[SendStatus] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_tblSMSSendQueueMain_SendMethod] ON [dbo].[tblSMSSendQueueMain]
(
[SendMethod] ASC,
[ID] DESC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
每个表大约有 13m 行 tblSMSSendQueueMainSendStatus 的 QueueID 列是 tblSMSSendQueueMain 的 ID 列的外键。
服务器有一个 8 核 Xeon CPU 和 8GB RAM。
我在分页计划中使用了 offset 和 fetch,它对于 100k 以下的偏移量来说是完美的,但是当偏移量增加(超过 100k)时,查询响应很慢,大约需要 5 或 6 秒才能运行。
这是我的查询:
SELECT q.ID
FROM tblSMSSendQueueMain q
INNER JOIN tblSMSSendQueueMainSendStatus qs
ON q.ID = qs.QueueID
WHERE 1 = 1
AND qs.SendStatus = 5
AND [SendMethod] = 19
ORDER BY q.ID desc OFFSET 10 * (1000000 - 1) ROWS
FETCH NEXT 10 ROWS ONLY
有人知道我哪里出错了吗?
【问题讨论】:
-
检查执行计划。
-
使用
OFFSET和FETCH进行分页几乎本质上是一种低效的操作,因为服务器实际上只能在到达您需要的位置之前计算100K 行——那里不是“大约正确”的概念,因此它必须尽最大努力为您提供您所要求的 10 行。由于没有人会在到达正确位置之前手动翻阅 10 万个结果,因此您最好使用实际值(无论是日期还是身份值)进行搜索,因为这些搜索可以通过索引提供服务。 -
@Larnu:我提到 100K 是因为 OP 提到从 100K 开始事情会变慢。我提到 this 是因为我不希望人们认为我在必要时无法数零。伙计们,在重要的时候,我完全可以。 :P 无论是从偏移量 100K 还是 1M 还是 10M 变慢都不会改变根本问题。
-
很公平,@JeroenMostert。我也不是要暗示你也看不懂零。 :)
标签: sql sql-server tsql keyset-pagination