我们正在使用在 SQL Server Enterprise 上运行的供应商应用程序,它COUNT
在处理大多数财务文档(订单、发票等)时在 Items 表上执行语句有一个相当烦人的怪癖。
例如 SELECT COUNT('A') FROM [dbo].[Items] T0
我相信这通常没问题,但是有超过 600 万条记录,并且需要大约 400 毫秒来计算它们。这可能构成整个处理时间的很大一部分。
该表已经有一个非常窄的非聚集索引(tinyint,加上聚集键),这是 SQL 在执行表扫描时使用的,所以我认为我们在这方面不能做得更好。
我知道有一些解决方案,如果可能,我们希望避免:
COUNT_BIG(*)
我们还有其他选择可以加快速度吗?
这是显示设置的要点:https : //gist.github.com/elvishfiend/5094f120b14f8ecfb325623edcb5f3eb
我们在处理一些与此类似的查询时遇到问题:
SELECT COUNT('A') FROM [dbo].[OINV] T0
INNER JOIN [dbo].[OCRD] T2 ON T2.[CardCode] = T0.[CardCode]
WHERE T0.[CardCode] = (@P2) OR T2.[FatherCard] = (@P3)
Run Code Online (Sandbox Code Playgroud)
它击中的索引定义为:
NONCLUSTERED INDEX [OCRD_FATHER] ON [dbo].[OCRD]
(
[FatherCard] ASC
) INCLUDE (CardCode)
NONCLUSTERED INDEX [OINV_CUSTOMER] ON [dbo].[OINV]
(
[CardCode] ASC
)
Run Code Online (Sandbox Code Playgroud)
他们目前需要 1-2 秒来运行,并返回 0 的计数(这是我们所期望的)。
我非常惊讶的是,它在进入哈希匹配之前没有过滤非聚集索引 - 它正在提供每一行。这些是供应商软件查询,因此很遗憾我们无法重写它们。
为什么会这样,有没有办法在不重写查询的情况下在进行哈希匹配之前将其更改为过滤?
示例数据设置
CREATE TABLE [dbo].[OCRD]
(
[FatherCard] NVARCHAR(50),
[CardCode] NVARCHAR(50)
);
INSERT INTO [dbo].[OCRD]
SELECT TOP (2076000) NEWID(),
NEWID()
FROM master..spt_values v1,
master..spt_values v2,
master..spt_values v3
CREATE TABLE …
Run Code Online (Sandbox Code Playgroud) 作为处理发票的一部分,我们的第 3 方 ERP 创建、查询,然后在其中一个 ERP 数据库表上删除视图。
我们对此有不同的担忧,但我真的很好奇:CREATE 或 DROP 语句中的任何一个都需要对数据库或视图中涉及的表使用模式修改锁吗?
如果没有,进程中是否还有其他需要我们关注的锁类型?