Far*_*oon 3 sql-server execution-plan nonclustered-index
我有两个结构相似的 UPDATE 查询,但其中一个的 SQL Server 查询计划显示正在使用的索引,而另一个仅显示常规表扫描。
以下是查询(根据查询计划,#1 不使用索引,#2 使用)-
UPDATE Payment_Metadata
SET
Payment_Metadata.CommodityCode = 'RAW MATERIALS',
Payment_Metadata.C1 = 'RAW MATERIALS',
Payment_Metadata.C2 = 'INGREDIENTS',
Payment_Metadata.C3 = 'OTHER ',
Payment_Metadata.RuleText = '---',
Payment_Metadata.LastUpdatedIndex = Payment_Metadata.LastUpdatedIndex + 1,
Payment_Metadata.IsExcluded = 0,
Payment_Metadata.LogText = 'Commodity>Raw Materials>Ingredients>Other'
FROM
Payment_Metadata
WHERE
Payment_Metadata.IsProcessed = 0
AND (Payment_Metadata.EnrichedVendor = 'NFL'
OR Payment_Metadata.Vendor_No = 'NFL')
Run Code Online (Sandbox Code Playgroud)
第二个查询使用索引:
UPDATE Payment_Metadata
SET
Payment_Metadata.CommodityCode = 'RAW MATERIALS',
Payment_Metadata.C1 = 'RAW MATERIALS',
Payment_Metadata.C2 = 'INGREDIENTS',
Payment_Metadata.C3 = 'OTHER ',
Payment_Metadata.RuleText = '---',
Payment_Metadata.LastUpdatedIndex = Payment_Metadata.LastUpdatedIndex + 1,
Payment_Metadata.IsExcluded = 0,
Payment_Metadata.LogText = 'Commodity>Raw Materials>Ingredients>Other'
FROM
Payment_Metadata
WHERE Payment_Metadata.IsProcessed = 0
AND (Payment_Metadata.EnrichedVendor = '0202054' OR
Payment_Metadata.Vendor_No = '0202054')
Run Code Online (Sandbox Code Playgroud)
以下是表定义:
CREATE TABLE [dbo].[Payment_Metadata](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Company_Code] [varchar](1024) NULL,
[Comp_Code_Desc] [varchar](1024) NULL,
[Vendor_Acct_Group] [varchar](1024) NULL,
[Vendor_No] [varchar](10) NULL,
[Vendor_Name] [varchar](1024) NULL,
[Vendor_ABN] [varchar](1024) NULL,
[Vendor_PTerm] [varchar](1024) NULL,
[Vendor_PTerm_Desc] [varchar](1024) NULL,
[Purchasing_Group] [varchar](1024) NULL,
[Purchasing_Group_Des] [varchar](1024) NULL,
[PO_DocType] [varchar](1024) NULL,
[PO_DocType_Desc] [varchar](1024) NULL,
[Purchasing_Document] [varchar](1024) NULL,
[PO_Date] [varchar](1024) NULL,
[PO_CreatedBy] [varchar](1024) NULL,
[Plant] [int] NULL,
[Item_Number] [varchar](1024) NULL,
[Material_Number] [varchar](1024) NULL,
[Material_Group] [varchar](7) NULL,
[Material_Group_Desc] [varchar](1024) NULL,
[Account_Assignment] [varchar](32) NULL,
[Acct_Assignment_Desc] [varchar](1024) NULL,
[GL_Account] [varchar](7) NULL,
[GL_Account_Desc] [varchar](1024) NULL,
[PO_Desc] [varchar](64) NULL,
[PO_Quantity] [decimal](10, 2) NULL,
[Order_UOM] [varchar](1024) NULL,
[Order_Price_Unit] [varchar](1024) NULL,
[Invoice_Receipt] [varchar](1024) NULL,
[Invoice_Reference] [varchar](1024) NULL,
[Invoice_Date] [datetime] NOT NULL,
[Invoice_Scan_Date] [datetime] NULL,
[Invoice_Item] [int] NULL,
[Invoice_Amount] [decimal](15, 2) NULL,
[GST] [decimal](10, 2) NOT NULL,
[Invoice_Gross_Amount] [decimal](15, 2) NULL,
[Currency] [varchar](1024) NULL,
[Document_Type] [varchar](1024) NULL,
[Document_Number] [varchar](1024) NULL,
[Document_Date] [datetime] NOT NULL,
[Posting_Date] [datetime] NOT NULL,
[Payment_Term] [varchar](1024) NULL,
[Baseline_Date] [datetime] NOT NULL,
[Due_Date] [datetime] NOT NULL,
[Payment_Document] [varchar](1024) NULL,
[Clearing_Date] [datetime] NOT NULL,
[CommodityCode] [varchar](128) NULL,
[RuleText] [nvarchar](max) NULL,
[IsProcessed] [bit] NOT NULL,
[DataSource] [varchar](5) NULL,
[IsContracted] [bit] NOT NULL,
[IsPreferred] [bit] NOT NULL,
[VendorRiskScore] [varchar](5) NULL,
[EnrichedVendor] [varchar](128) NULL,
[LastUpdatedIndex] [int] NOT NULL,
[LogText] [nvarchar](max) NULL,
[IsExcluded] [bit] NOT NULL,
[C1] [varchar](50) NULL,
[C2] [varchar](50) NULL,
[C3] [varchar](50) NULL,
[OriginalVendor] [varchar](60) NULL,
[AdjustedAmount] [decimal](15, 2) NULL
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
如您所见,该WHERE子句中唯一的变化是数字与非数字字符的使用(我怀疑这不应该影响查询计划?)
每个列 EnrichedVendor 和 Vendor_No 上都有一个非聚集索引。
任何帮助,将不胜感激。
更新:包括下面的查询计划,我注意到查询 #1 建议了一个索引(绿色)。这可能是答案的解决方案。

SQL Server 使用统计信息来确定执行计划。如果索引可用,则统计信息也可用,SQL Server 将确定最少工作的路径。这可能是使用索引或进行表扫描。
在您的示例中,SQL 服务器已确定表扫描的工作量少于索引查找和书签查找。
您可以看到您的查询之一“选择性较低”,即它可能更新更多记录,这意味着需要更多书签查找来满足第二个查询。SQL Server 只是估计对于该查询,索引查找 + 书签查找的总和比简单地执行表扫描要多得多。
由于 SQL Server 读取整个页面,而不是记录,因此您的查询(如统计数据所示)需要有足够的选择性才能使用索引,如果 SQL Server 估计它无论如何都必须读取每个页面,那么它将继续表扫描。
| 归档时间: |
|
| 查看次数: |
1759 次 |
| 最近记录: |