我有一个与此类似的数据库结构,
CREATE TABLE [dbo].[Dispatch](
[DispatchId] [int] NOT NULL,
[ContractId] [int] NOT NULL,
[DispatchDescription] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Dispatch] PRIMARY KEY CLUSTERED
(
[DispatchId] ASC,
[ContractId] 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 TABLE [dbo].[DispatchLink](
[ContractLink1] [int] NOT NULL,
[DispatchLink1] [int] NOT NULL,
[ContractLink2] [int] NOT NULL,
[DispatchLink2] [int] NOT NULL
) ON [PRIMARY]
GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (1, 1, N'Test') …Run Code Online (Sandbox Code Playgroud) 为什么下面的查询很慢?
select count(*)
from [dbo].[mt_dispatch_link]
, [dbo].[_mt_dispatch] [_mt_dispatch]
where (mt_dispatch_link.contract_id_1 = _mt_dispatch.contract_id
and mt_dispatch_link.dispatch_id_1 = _mt_dispatch.dispatch_id)
or (mt_dispatch_link.contract_id_2 = _mt_dispatch.contract_id
and mt_dispatch_link.dispatch_id_2 = _mt_dispatch.dispatch_id)
Run Code Online (Sandbox Code Playgroud)

这需要 10 多分钟,然后我倾向于在那个时候停止它。我的问题更多是关于如何理解查询计划。
查看查询计划,我可以看到底部聚集索引扫描返回大约 250000 条记录,但成本为 0% 并且它正在放入临时表中。
顶部索引扫描大约是 25000 条记录。
但是 95% 的成本来自嵌套连接。我应该从中得出什么结论?
上面的查询计划显示了两次索引扫描,是说它在做 25000 + 250000 次索引扫描,还是说它在做 25000 * 250000 次索引扫描?
如果我将查询更改为此(添加FORCESEEK):
select count(*)
from [dbo].[mt_dispatch_link]
, [dbo].[_mt_dispatch] [_mt_dispatch]
WITH (FORCESEEK)
where (mt_dispatch_link.contract_id_1 = _mt_dispatch.contract_id
and mt_dispatch_link.dispatch_id_1 = _mt_dispatch.dispatch_id)
or (mt_dispatch_link.contract_id_2 = _mt_dispatch.contract_id
and mt_dispatch_link.dispatch_id_2 = _mt_dispatch.dispatch_id)
Run Code Online (Sandbox Code Playgroud)
我最终得到了一个更好的计划,查询立即运行:

我在两个表上运行了更新统计信息。可惜没修好。表设计不是很好,所以我认为 SQL Server 并不真正理解,因此提出了一个糟糕的查询计划。有关 …