估计行数 > 实际行数是一个需要担心的问题吗?

Har*_*ngh 1 performance index sql-server t-sql execution-plan

我有一个表格[order],其中一个简单的选择以一种奇怪的方式显示了估计行数和实际行数之间的主要差异。

在这种情况下,一般估计行数与实际行数相比偏斜,这完全具有讽刺意味。此外,“执行次数”为 1。

在此处输入图片说明

询问 :

SELECT 
ord.paymentmode AS [HowTheyPaid],
ord.id AS [OrderId],
ord.ISBackEndSystemMigrated,
ord.ISDuplicate,
ord.ISMerged
FROM 

DedicatedDentalPlans_Stage.dbo.[order] ord
WHERE 
ISBackEndSystemMigrated=0 
AND ISDuplicate = 1
Run Code Online (Sandbox Code Playgroud)

桌子

USE [DedicatedDentalPlans_Stage]
GO

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF_Order_ISBackEnd]') AND type = 'D')
BEGIN
ALTER TABLE [dbo].[Order] DROP CONSTRAINT [DF_Order_ISBackEnd]
END

GO

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF__Order__ISDuplica__382F5661]') AND type = 'D')
BEGIN
ALTER TABLE [dbo].[Order] DROP CONSTRAINT [DF__Order__ISDuplica__382F5661]
END

GO

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DF__Order__ISMerged__39237A9A]') AND type = 'D')
BEGIN
ALTER TABLE [dbo].[Order] DROP CONSTRAINT [DF__Order__ISMerged__39237A9A]
END

GO



/****** Object:  Table [dbo].[Order]    Script Date: 03/09/2016 02:11:57 ******/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Order]') AND type in (N'U'))
DROP TABLE [dbo].[Order]
GO

/****** Object:  Table [dbo].[Order]    Script Date: 03/09/2016 02:11:57 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Order](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [SubscriberId] [int] NOT NULL,
    [BillingAddressId] [int] NOT NULL,
    [ShippingAddressId] [int] NULL,
    [OrderStatusId] [int] NOT NULL,
    [ShippingStatusId] [int] NOT NULL,
    [PaymentStatusId] [int] NOT NULL,
    [PaymentMethodSystemName] [nvarchar](max) NULL,
    [OrderDiscount] [decimal](18, 4) NOT NULL,
    [OrderTotal] [decimal](18, 4) NOT NULL,
    [SystemUserId] [int] NULL,
    [UserType] [int] NULL,
    [PaymentMode] [varchar](20) NULL,
    [Deleted] [bit] NOT NULL,
    [AutomaticRenewal] [bit] NULL,
    [CreatedOnUtc] [datetime] NOT NULL,
    [ETLControlId] [int] NULL,
    [ETLGenerationId] [int] NULL,
    [ISBackEndSystemMigrated] [bit] NULL,
    [CheckNumber] [varchar](20) NULL,
    [ISDuplicate] [bit] NULL,
    [ISMerged] [bit] NULL,
 CONSTRAINT [PK__Order__3214EC0722AA2996] 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

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[Order] ADD  CONSTRAINT [DF_Order_ISBackEnd]  DEFAULT ((0)) FOR [ISBackEndSystemMigrated]
GO

ALTER TABLE [dbo].[Order] ADD  DEFAULT ((0)) FOR [ISDuplicate]
GO

ALTER TABLE [dbo].[Order] ADD  DEFAULT ((0)) FOR [ISMerged]
GO
Run Code Online (Sandbox Code Playgroud)

解决方案 到目前为止没有结果:更新了与具有完全扫描的相同索引和聚集索引相关的统计信息。

Pau*_*ite 5

在呈现的特定场景中:

,估计行数和实际行数之间的差异并不重要。有两个关键信息可以支持该声明:

  1. 该查询符合一个平凡的计划;和
  2. 该查询进一步符合简单参数化的要求

这从 Seek Predicate 文本中可以清楚地看出,其中ISBackEndSystemMigratedISDuplicate的文字值已替换为参数标记@1@2

寻找谓词

这意味着选择的计划与 SQL Server 为所有可能的文字值选择的计划相同。琐碎计划将简单查询的编译时间降至最低;简单的参数化促进了执行计划的重用。

此外,明显的基数不匹配是由于 SQL Server 生成了平均情况的估计值(所有可能的文字值)。

在其他情况下,当然基数估计不准确可能很重要。诀窍是知道什么时候重要或不重要。这里没有一般的安全经验法则,大部分都归结为经验。查询调优不全是科学;也有艺术的空间:)