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
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;
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);
Voir mon article colonnes calculées correctement persistées pour plus de détails.
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.