Int / SmallintからVarcharへの暗黙の変換が発生するのはなぜですか?それは本当にカーディナリティの見積もりに影響を与えますか?


11

実際の実行プランでプラン表示分析(SSMS)を使用して、パフォーマンスの遅いクエリをトラブルシューティングしようとしています。分析ツールは、行数の見積もりが計画のいくつかの場所で返された結果からずれていることを指摘し、さらにいくつかの暗黙の変換警告を与えます。

これらのintからVarcharへの暗黙的な変換を理解できません-参照されるフィールドはクエリのパラメーター/フィルターの一部ではなく、関係するすべてのテーブルで列のデータ型は同じです:

以下のCardinalityEstimate警告が表示されます。

式の型変換(CONVERT_IMPLICIT(varchar(12)、[ccd]。[profileid]、0))は、クエリプランの選択で "CardinalityEstimate"に影響を与える可能性があります-このフィールドは、私のDB内のすべての整数です

式の型変換(CONVERT_IMPLICIT(varchar(6)、[ccd]。[nodeid]、0))は、クエリプランの選択で "CardinalityEstimate"に影響を与える可能性があります-このフィールドは、私のDBのあらゆる場所でsmallintです

式の型変換(CONVERT_IMPLICIT(varchar(6)、[ccd]。[sessionseqnum]、0))は、クエリプランの選択で "CardinalityEstimate"に影響を与える可能性があります-このフィールドは、DB内のあらゆる場所で小さな整数です

式の型変換(CONVERT_IMPLICIT(varchar(41)、[ccd]。[sessionid]、0))は、クエリプランの選択で "CardinalityEstimate"に影響する可能性があります-このフィールドは、DBのすべての場所で10進数です

[編集]参照用のクエリと実際の実行計画は次の とおりですhttps://www.brentozar.com/pastetheplan/?id=SysYt0NzN

そして、テーブルの定義。

/****** 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

回答:


11

暗黙的な変換は、計算された列によって引き起こされます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,
);

上記の簡略化されたテーブルを前提として、以下の単純なステートメントは、質問で与えられたものと同じ暗黙の変換警告を生成します。

SELECT T.*
FROM dbo.Test AS T;

警告付きの計画

ドキュメントから(強調を追加):

CONCAT 連結する前に、すべての引数を暗黙的に文字列型に変換します。

警告は、SQL Serverが永続化された値を使用しない代替案を検討するが、値を明示的に計算するときに追加されます。最終計画で永続化された値が使用されている場合、警告は削除されません。

この場合、警告は無視しても問題ありません。これは、私が知る限り、実行計画にも当てはまります-に含まれる暗黙の変換CONCATは計画の選択に悪影響を及ぼしません。

ドキュメント化されておらず、サポートされていないトレースフラグ176を使用すると、計算列の展開が永続化されず、警告が削除されます。

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

TF 176

詳細については、私の記事「適切に永続化された計算列」を参照してください。


5

これらは、暗黙の変換警告が表示されるフィールドです。

  • [ccd].[profileid] (varchar(12)への整数)
  • [ccd].[nodeid] (smallcharからvarchar(6)へ)
  • [ccd].[sessionseqnum] (smallcharからvarchar(6)へ)
  • [ccd].[sessionid] (varchar(41)の10進数)

参照されるフィールドは、クエリのパラメーター/フィルターの一部ではありません

確かに、あなたの参加条件では。ここでは、ccd.profileidがフィルターとして(および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

関連するすべてのテーブルで、列のデータ型は同じです

テーブルの定義を再確認してください。

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

彼らが使用していると思われるデータ型を使用していないようです。

そしてそれは本当にカーディナリティの見積もりに影響を与えていますか?

あなたが提供した情報に基づいて、私の答えにはいくつかの推測が続いています。実際の実行計画とテーブル定義を質問に追加して、これらの暗黙的な変換の問題に関係している可能性のあるすべての詳細がわかるようにすることをお勧めします。

一般に、結合条件の暗黙的な変換は、見積もりで重大な問題を引き起こす可能性があります。これが実際の実行計画を見ずにあなたのケースで起こっているかどうかを言うのは難しいです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.