web-dev-qa-db-fra.com

Pourquoi est-ce que je reçois une conversion implicite de Int / Smallint en Varchar, et est-ce vraiment un impact sur les estimations de cardinalité?

J'essaie de déranger une requête lente à l'aide de l'analyse du plan (SSMS) sur le plan d'exécution actuel. L'outil d'analyse souligne que les estimations du nombre de lignes sont éteintes des résultats retournés dans quelques endroits dans le plan et me donnent en outre des avertissements de conversion implicites.

Je ne comprends pas ces conversions implicites d'INT sur Varchar- Les champs référencés ne font partie d'aucun paramètre/filtre sur la requête et dans toutes les tables impliquées, les types de données de colonne sont les mêmes:

Je reçois les avertissements ci-dessous de cardinalité:

Type de conversion dans l'expression (convert_implicit (variateur (variateur (12), [CCD]. [Profiled], 0)) peut affecter "cardinalitéesttime" dans le choix de plan de requête --Ce champ est un entier partout dans mon dB

Type de conversion dans l'expression (convert_implicite (varchar (6), [CCD]. [NodeID], 0)) peut affecter "cardinalitéestimée" dans le choix de plan de requête --Ce champ est un smallint partout dans mon dB

Type de conversion dans l'expression (convert_implicit (varchar (6), [CCD]. [SessionSeqnum], 0)) peut affecter "cardinalitéestimée" dans le choix de plan de requête --Ce champ est une petite chose partout dans mon dB

Type de conversion dans l'expression (convert_implicite (Varchar (41), [CCD]. [SessionId], 0)) peut affecter "cardinalitéestimée" dans le choix de plan de requête --Ce champ est une décimale partout dans mon dB

[Modifier] Voici le plan d'exécution de la requête et réelle de référence https://www.brentozar.com/pastetheplan/?id=sysyt0nzn

Et définitions de table ..

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

Les conversions implicites sont causées par la colonne calculée 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,
);

Compte tenu de la table simplifiée ci-dessus, la déclaration simple ci-dessous génère les mêmes avertissements de conversion implicites indiqués dans la question:

SELECT T.*
FROM dbo.Test AS T;

Plan with warnings

De - la documentation (accent ajouté):

CONCAT convertit implicitement Tous les arguments des types de chaîne avant la concaténation.

L'avertissement est ajouté lorsque SQL Server considère une alternative de plan qui n'utilise pas la valeur persistée, mais calcule explicitement la valeur. L'avertissement n'est pas supprimé si le plan final utilise la valeur persistée.

Les avertissements peuvent être ignorés en toute sécurité dans ce cas. Cela s'applique également à votre plan d'exécution, autant que je puisse dire - les conversions implicites impliquées dans la CONCAT ne concernent pas de choix de planification.

Utilisation non-documenté et non pris en charge Drapeau de trace 176 empêche l'expansion de la colonne calculée persistée et supprime les avertissements:

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

with tf 176

Voir mon article colonnes calculées correctement persistées pour plus de détails.

11
Paul White 9

Ce sont les champs que vous obtenez des avertissements de conversion implicites sur:

  • [ccd].[profileid] (Int à Varchar (12))
  • [ccd].[nodeid] (Smallint to Varchar (6))
  • [ccd].[sessionseqnum] (Smallint to Varchar (6))
  • [ccd].[sessionid] (décimale à Varchar (41))

Les champs référencés ne font partie d'aucun paramètre/filtre sur la requête

Bien sûr, dans vos conditions de jointure. Voici l'endroit où CCD.ProfileID est utilisé comme filtre (ainsi que dans une jointure à l'agentConnectorDetail):

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

et dans toutes les tables impliquées, les types de données de colonne sont les mêmes

Vous voudrez peut-être vérifier les définitions de la table pour

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

On dirait qu'ils n'utilisent pas les types de données que vous pensez qu'ils utilisent.

et est-ce vraiment sur l'impact des estimations de la cardinalité?

Il y a quelques devinations dans ma réponse en fonction des informations que vous avez fournies. Je vous encourage à ajouter le plan d'exécution et les définitions de table actuels à votre question afin que tous les détails impliquaient de jouer dans ces problèmes de conversion implicites.

En général, la conversion implicite sur les conditions de jointure peut causer sérieux problèmes avec des estimations. Il est difficile de dire que cela se passe dans votre cas sans voir le plan d'exécution réel.

5
Josh Darnell