1

对于一个非常简单的 SQL 查询生成的查询计划,我遇到了一个非常奇怪的问题。该查询正在搜索全文索引,并返回记录数。

出于某种原因,此 SQL 查询正在对索引产生非聚集扫描,我认为这样做不是最佳选择。我相信对于计数,由于主键在全文索引中,因此只需要聚集查找。

有人会对为什么使用这样的查询计划有任何建议吗?

奇怪的是,由于 SQL 的变体略有不同,有时它使用聚集索引(非常快),有时它使用非聚集搜索。

这是查询:

EXEC sp_executesql N'SELECT count(T.[ID])
FROM [dbo].[Item] AS T
WHERE CONTAINS (
        (
            T.[Description]
            )
        ,@P0M
        )
'
    ,N'@P0M nvarchar(4000)'
    ,@P0M = N'"mouse*"'

这是查询计划: https ://i.stack.imgur.com/1XJcf.png如您所见,非集群搜索成本为 51%,加上位图上的 8% 并行度和 15% 哈希匹配。

该表有很多数据。超过 300 万条记录。

非常感谢

编辑:这是计划:https ://www.brentozar.com/pastetheplan/?id=HyiABrg1K

这是表定义:

CREATE TABLE [dbo].[Item](
    [ID] [uniqueidentifier] NOT NULL,
    [Description] [nvarchar](500) NOT NULL,
    [Manufacturer] [uniqueidentifier] NOT NULL,
    [Manufacturer Name] [nvarchar](100) NULL,
    [Manufacturer Item No.] [nvarchar](50) NOT NULL,
    [BC Item No.] [varchar](20) NULL,
    [CRM Item No.] [varchar](50) NULL,
    [Category] [uniqueidentifier] NULL,
    [Version No.] [varchar](50) NULL,
    [Blocked] [bit] NULL,
    [UNSPSC Code] [int] NULL,
    [Barcode] [char](13) NULL,
    [Last Update Date Time] [datetime] NULL,
    [Weight (kg)] [decimal](18, 3) NULL,
    [RRP] [decimal](18, 2) NULL,
    [RRP Currency] [uniqueidentifier] NULL,
    [timestamp] [timestamp] NOT NULL,
 CONSTRAINT [PK_Item] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 99, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

还有很多外键。

这是唯一的其他索引:

CREATE UNIQUE NONCLUSTERED INDEX [Manufacturer Part No] ON [dbo].[Item]
(
    [Manufacturer] ASC,
    [Manufacturer Item No.] ASC
)
INCLUDE([ID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
4

1 回答 1

0

经过大量挖掘,我发现了这个Query Optimizer Gone Wild - Full-Text Search Query Plans

看起来这是设计使然。ContainsTable 查询不需要加入即可获得行数。

CONTAINS 函数还必须扫描源表上的索引以获取计数

于 2021-08-16T09:42:49.830 回答