Tại sao tôi nhận được một chuyển đổi ngầm định của Int / Smallint sang Varchar, và nó có thực sự ảnh hưởng đến Ước tính Cardinality không?


11

Tôi đang cố gắng xử lý một truy vấn hiệu suất chậm bằng cách sử dụng Phân tích kế hoạch hiển thị (SSMS) trên kế hoạch thực hiện thực tế. Công cụ Phân tích chỉ ra rằng các ước tính cho số lượng hàng bị tắt từ các kết quả được trả về ở một vài vị trí trong kế hoạch và tiếp tục cung cấp cho tôi một số cảnh báo chuyển đổi ngầm định.

Tôi không hiểu các chuyển đổi ngầm định này của int qua Varchar- Các trường được tham chiếu không phải là một phần của bất kỳ tham số / bộ lọc nào trên truy vấn và trong tất cả các bảng có liên quan đến các kiểu dữ liệu cột đều giống nhau:

Tôi nhận được các Cảnh báo Cardinality dưới đây:

Chuyển đổi loại trong biểu thức (CONVERT_IMPLICIT (varchar (12), [ccd]. [Profileid], 0)) có thể ảnh hưởng đến "CardinalityEstimate" trong lựa chọn gói truy vấn - Trường này là số nguyên ở mọi nơi trong DB của tôi

Chuyển đổi loại trong biểu thức (CONVERT_IMPLICIT (varchar (6), [ccd]. [Nodeid], 0)) có thể ảnh hưởng đến "CardinalityEstimate" trong lựa chọn gói truy vấn - Trường này là một phần nhỏ ở mọi nơi trong DB của tôi

Chuyển đổi loại trong biểu thức (CONVERT_IMPLICIT (varchar (6), [ccd]. [Sessionseqnum], 0)) có thể ảnh hưởng đến "CardinalityEstimate" trong lựa chọn gói truy vấn - Trường này là một phần nhỏ ở mọi nơi trong DB của tôi

Chuyển đổi loại trong biểu thức (CONVERT_IMPLICIT (varchar (41), [ccd]. [Sessionid], 0)) có thể ảnh hưởng đến "CardinalityEstimate" trong lựa chọn gói truy vấn - Trường này là số thập phân ở mọi nơi trong DB của tôi

[EDIT] Đây là truy vấn và kế hoạch thực hiện thực tế để tham khảo https://www.brentozar.com/pastetheplan/?id=SysYt0NzN

Và định nghĩa bảng ..

/****** Object:  Table [dbo].[agentconnectiondetail]    Script Date: 1/10/2019 9:10:04 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[agentconnectiondetail](
    [sessionid] [decimal](18, 0) NOT NULL,
    [sessionseqnum] [smallint] NOT NULL,
    [nodeid] [smallint] NOT NULL,
    [profileid] [int] NOT NULL,
    [resourceid] [int] NOT NULL,
    [startdatetime] [datetime2](7) NOT NULL,
    [enddatetime] [datetime2](7) NOT NULL,
    [qindex] [smallint] NOT NULL,
    [gmtoffset] [smallint] NOT NULL,
    [ringtime] [smallint] NULL,
    [talktime] [smallint] NULL,
    [holdtime] [smallint] NULL,
    [worktime] [smallint] NULL,
    [callwrapupdata] [varchar](40) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [callresult] [smallint] NULL,
    [dialinglistid] [int] NULL,
    [convertedStartDatetimelocal] [datetime2](7) NULL,
    [convertedEndDatetimelocal] [datetime2](7) NULL,
 CONSTRAINT [PK_agentconnectiondetail] PRIMARY KEY CLUSTERED 
(
    [sessionid] ASC,
    [sessionseqnum] ASC,
    [nodeid] ASC,
    [profileid] ASC,
    [resourceid] ASC,
    [startdatetime] ASC,
    [qindex] 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
/****** Object:  Table [dbo].[contactcalldetail]    Script Date: 1/10/2019 9:10:04 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[contactcalldetail](
    [sessionid] [decimal](18, 0) NOT NULL,
    [sessionseqnum] [smallint] NOT NULL,
    [nodeid] [smallint] NOT NULL,
    [profileid] [int] NOT NULL,
    [contacttype] [smallint] NOT NULL,
    [contactTypeDescription] [varchar](20) COLLATE Latin1_General_CI_AS NULL,
    [contactdisposition] [smallint] NOT NULL,
    [contactdispositionDescription] [varchar](20) COLLATE Latin1_General_CI_AS NULL,
    [dispositionreason] [varchar](100) COLLATE Latin1_General_CI_AS NULL,
    [originatortype] [smallint] NOT NULL,
    [originatorTypeDescription] [varchar](20) COLLATE Latin1_General_CI_AS NULL,
    [originatorid] [int] NULL,
    [originatordn] [varchar](30) COLLATE Latin1_General_CI_AS NULL,
    [destinationtype] [smallint] NULL,
    [destinationTypeDescription] [varchar](20) COLLATE Latin1_General_CI_AS NULL,
    [destinationid] [int] NULL,
    [destinationdn] [varchar](30) COLLATE Latin1_General_CI_AS NULL,
    [startdatetimeUTC] [datetime2](7) NOT NULL,
    [enddatetimeUTC] [datetime2](7) NOT NULL,
    [gmtoffset] [smallint] NOT NULL,
    [callednumber] [varchar](30) COLLATE Latin1_General_CI_AS NULL,
    [origcallednumber] [varchar](30) COLLATE Latin1_General_CI_AS NULL,
    [applicationtaskid] [decimal](18, 0) NULL,
    [applicationid] [int] NULL,
    [applicationname] [varchar](30) COLLATE Latin1_General_CI_AS NULL,
    [connecttime] [smallint] NULL,
    [customvariable1] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable2] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable3] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable4] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable5] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable6] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable7] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable8] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable9] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [customvariable10] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [accountnumber] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [callerentereddigits] [varchar](40) COLLATE Latin1_General_CI_AS NULL,
    [badcalltag] [char](1) COLLATE Latin1_General_CI_AS NULL,
    [transfer] [bit] NULL,
    [NextSeqNum] [smallint] NULL,
    [redirect] [bit] NULL,
    [conference] [bit] NULL,
    [flowout] [bit] NULL,
    [metservicelevel] [bit] NULL,
    [campaignid] [int] NULL,
    [origprotocolcallref] [varchar](32) COLLATE Latin1_General_CI_AS NULL,
    [destprotocolcallref] [varchar](32) COLLATE Latin1_General_CI_AS NULL,
    [convertedStartDatetimelocal] [datetime2](7) NULL,
    [convertedEndDatetimelocal] [datetime2](7) NULL,
    [AltKey]  AS (concat([sessionid],[sessionseqnum],[nodeid],[profileid]) collate database_default) PERSISTED NOT NULL,
    [PrvSeqNum] [smallint] NULL,
 CONSTRAINT [PK_contactcalldetail] PRIMARY KEY CLUSTERED 
(
    [sessionid] ASC,
    [sessionseqnum] ASC,
    [nodeid] ASC,
    [profileid] 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
/****** Object:  Table [dbo].[contactqueuedetail]    Script Date: 1/10/2019 9:10:04 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[contactqueuedetail](
    [sessionid] [decimal](18, 0) NOT NULL,
    [sessionseqnum] [smallint] NOT NULL,
    [profileid] [int] NOT NULL,
    [nodeid] [smallint] NOT NULL,
    [targetid] [int] NOT NULL,
    [targettype] [smallint] NOT NULL,
    [targetTypeDescription] [varchar](10) COLLATE Latin1_General_CI_AS NULL,
    [qindex] [smallint] NOT NULL,
    [queueorder] [smallint] NOT NULL,
    [disposition] [smallint] NULL,
    [dispositionDescription] [varchar](50) COLLATE Latin1_General_CI_AS NULL,
    [metservicelevel] [bit] NULL,
    [queuetime] [smallint] NULL,
 CONSTRAINT [PK_contactqueuedetail] PRIMARY KEY CLUSTERED 
(
    [sessionid] ASC,
    [sessionseqnum] ASC,
    [profileid] ASC,
    [nodeid] ASC,
    [targetid] ASC,
    [targettype] ASC,
    [qindex] 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
/****** Object:  Index [<Name of Missing Index, sysname,>]    Script Date: 1/10/2019 9:10:04 AM ******/
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] ON [dbo].[contactcalldetail]
(
    [convertedStartDatetimelocal] ASC
)
INCLUDE (   [sessionid],
    [sessionseqnum],
    [nodeid],
    [profileid]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
/****** Object:  Index [idx_CCD_ContactType_DestType_StDtLocal]    Script Date: 1/10/2019 9:10:04 AM ******/
CREATE NONCLUSTERED INDEX [idx_CCD_ContactType_DestType_StDtLocal] ON [dbo].[contactcalldetail]
(
    [destinationtype] ASC,
    [contacttype] ASC,
    [convertedStartDatetimelocal] ASC
)
INCLUDE (   [sessionid],
    [sessionseqnum],
    [nodeid],
    [profileid],
    [convertedEndDatetimelocal]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
/****** Object:  Index [idx_CQD_Profile_Traget_TargetType]    Script Date: 1/10/2019 9:10:04 AM ******/
CREATE NONCLUSTERED INDEX [idx_CQD_Profile_Traget_TargetType] ON [dbo].[contactqueuedetail]
(
    [profileid] ASC,
    [targetid] ASC,
    [targettype] ASC
)
INCLUDE (   [targetTypeDescription],
    [queueorder],
    [disposition],
    [dispositionDescription],
    [queuetime]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Câu trả lời:


11

Các chuyển đổi ngầm định được gây ra bởi cột được tính toán AltKey:

CREATE TABLE dbo.Test
(
    [sessionid] [decimal](18, 0) NOT NULL,
    [sessionseqnum] [smallint] NOT NULL,
    [nodeid] [smallint] NOT NULL,
    [profileid] [int] NOT NULL,
    [AltKey] AS 
        CONCAT
        (
            [sessionid],
            [sessionseqnum],
            [nodeid],
            [profileid]
        ) PERSISTED NOT NULL,
);

Với bảng được đơn giản hóa ở trên, câu lệnh đơn giản dưới đây tạo ra các cảnh báo chuyển đổi ngầm định được đưa ra trong câu hỏi:

SELECT T.*
FROM dbo.Test AS T;

Lập kế hoạch với các cảnh báo

Từ tài liệu (nhấn mạnh thêm):

CONCAT ngầm chuyển đổi tất cả các đối số thành các kiểu chuỗi trước khi nối.

Cảnh báo được thêm vào khi SQL Server xem xét một phương án thay thế không sử dụng giá trị bền vững, nhưng tính toán giá trị một cách rõ ràng. Cảnh báo không được xóa nếu gói cuối cùng sử dụng giá trị bền vững.

Các cảnh báo có thể được bỏ qua một cách an toàn trong trường hợp này. Điều này cũng áp dụng cho kế hoạch thực hiện của bạn, theo như tôi có thể nói - các chuyển đổi ngầm liên quan đến việc CONCATnày không ảnh hưởng xấu đến lựa chọn kế hoạch.

Sử dụng cờ theo dõi không có giấy tờ và không được hỗ trợ 176 sẽ ngăn chặn việc mở rộng cột được tính toán bền vững và xóa các cảnh báo:

SELECT * 
FROM dbo.Test AS T
OPTION (QUERYTRACEON 176);

với tf 176

Xem bài viết của tôi Cột được tính toán đúng cách để biết thêm chi tiết.


5

Đây là các trường bạn đang nhận được cảnh báo chuyển đổi ngầm về:

  • [ccd].[profileid] (int đến varar (12))
  • [ccd].[nodeid] (smallint to varchar (6))
  • [ccd].[sessionseqnum] (smallint to varchar (6))
  • [ccd].[sessionid] (số thập phân đến varchar (41))

Các trường được tham chiếu không phải là một phần của bất kỳ tham số / bộ lọc nào trên truy vấn

Chắc chắn họ là, trong điều kiện tham gia của bạn. Đây là nơi ccd.profileid đang được sử dụng làm bộ lọc (cũng như trong liên kết với agentconnectiondetail):

FROM contactcalldetail ccd 
    INNER JOIN contactqueuedetail csqd 
        ON ccd.sessionID=csqd.sessionid 
            AND ccd.sessionSeqNum=csqd.sessionSeqNum 
            AND ccd.nodeID=csqd.nodeID 
            AND ccd.profileid=csqd.profileid -- Right here

và trong tất cả các bảng liên quan đến các kiểu dữ liệu cột là như nhau

Bạn có thể muốn kiểm tra lại các định nghĩa bảng cho

  • contactcalldetail.profileid
  • contactqueuedetail.profileid
  • agentconnectiondetail .profileid

Có vẻ như họ không sử dụng các loại dữ liệu mà bạn nghĩ rằng họ đang sử dụng.

và nó có thực sự ảnh hưởng đến Ước tính Cardinality không?

Có một số phỏng đoán đang diễn ra trong câu trả lời của tôi dựa trên thông tin bạn đã cung cấp. Tôi khuyến khích bạn thêm kế hoạch thực hiện và định nghĩa bảng thực tế vào câu hỏi của bạn để chúng tôi có tất cả các chi tiết liên quan có thể có trong các vấn đề chuyển đổi ngầm định này.

Nói chung, chuyển đổi ngầm định trong điều kiện tham gia có thể gây ra vấn đề nghiêm trọng với ước tính. Thật khó để nói nếu điều này xảy ra trong trường hợp của bạn mà không thấy kế hoạch thực hiện thực tế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.