Bonjour,

Nous avons actuellement sur notre serveur de production deux tables définies comme cela:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
CREATE TABLE [PLAN_TRI](
	[NO_PLAN_TRI] [INT] IDENTITY(1,1) NOT NULL,
	[DATE_CREATION] [DATETIME] NOT NULL,
	[CODE_PLAN_TRI] [VARCHAR](50) NOT NULL,
	[LIBELLE] [VARCHAR](50) NULL,
 CONSTRAINT [PK_PLAN_TRI_NO_PLAN_TRI] PRIMARY KEY CLUSTERED 
(
	[NO_PLAN_TRI] 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
 
CREATE TABLE [EVENEMENT_PLAN_TRI](
	[NO_EVENEMENT_PLAN_TRI] [INT] IDENTITY(1,1) NOT NULL,
	[NO_PLAN_TRI] [INT] NOT NULL,
	[ETAT_PLAN_TRI] [TINYINT] NOT NULL,
	[DATE_EVENEMENT] [DATETIME] NOT NULL,
	[NO_UTILISATEUR] [INT] NULL,
 CONSTRAINT [PK_EVENEMENT_PLAN_TRI_NO_EVENEMENT_PLAN_TRI] PRIMARY KEY CLUSTERED 
(
	[NO_EVENEMENT_PLAN_TRI] 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
 
ALTER TABLE [EVENEMENT_PLAN_TRI]  WITH CHECK ADD  CONSTRAINT [FK_EVENEMENT_PLAN_TRI_ETAT_PLAN_TRI] FOREIGN KEY([ETAT_PLAN_TRI])
REFERENCES [ETAT_PLAN_TRI] ([ETAT_PLAN_TRI])
GO
 
ALTER TABLE [EVENEMENT_PLAN_TRI] CHECK CONSTRAINT [FK_EVENEMENT_PLAN_TRI_ETAT_PLAN_TRI]
GO
 
ALTER TABLE [EVENEMENT_PLAN_TRI]  WITH CHECK ADD  CONSTRAINT [FK_EVENEMENT_PLAN_TRI_NO_PLAN_TRI] FOREIGN KEY([NO_PLAN_TRI])
REFERENCES [PLAN_TRI] ([NO_PLAN_TRI])
GO
 
ALTER TABLE [EVENEMENT_PLAN_TRI] CHECK CONSTRAINT [FK_EVENEMENT_PLAN_TRI_NO_PLAN_TRI]
GO
L'idée est d'avoir une table contenant l'ensemble des plans de tri et la seconde contient les evènements historisés sur chacun d'entre eux. On n'utilise plus de champ 'etat' directement dans la table.

Les indexes posé sur cette table sont :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
 
CREATE NONCLUSTERED INDEX [IX_EVENEMENT_PLAN_TRI_ETAT_PLAN_TRI] ON [EVENEMENT_PLAN_TRI]
(
	[ETAT_PLAN_TRI] ASC
)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
 
CREATE NONCLUSTERED INDEX [IX_EVENEMENT_PLAN_TRI_NO_PLAN_TRI] ON [EVENEMENT_PLAN_TRI]
(
	[NO_PLAN_TRI] ASC
)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
 
CREATE NONCLUSTERED INDEX [IX_DATE_EVENEMENT] ON [EVENEMENT_PLAN_TRI]
(
	[NO_PLAN_TRI] ASC
	[DATE_EVENEMENT]ASC
)
INCLUDE (ETAT_PLAN_TRI)
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
Le problème c'est que les applications utilisant la base on besoin de connaitre très souvent le type du dernier evenement survenu sur un plan de tri.
Pour cela on effectue une requete du genre (codée dans une vue pour utiliser toujours la même dans les applications):

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
		WITH
		CTE_EPT AS
		( SELECT
			EPT.NO_PLAN_TRI
			, MAX( EPT.DATE_EVENEMENT ) MAX_DATE_EVENEMENT
		FROM
			EVENEMENT_PLAN_TRI EPT
		INNER JOIN
			PLAN_TRI PTR
		ON
			PTR.NO_PLAN_TRI = EPT.NO_PLAN_TRI
		GROUP BY
			EPT.NO_PLAN_TRI
		)
		, CTE_PTR AS
		( SELECT
			EPT.NO_PLAN_TRI
		FROM
			CTE_EPT
		INNER JOIN
			EVENEMENT_PLAN_TRI EPT
		ON
			CTE_EPT.NO_PLAN_TRI = EPT.NO_PLAN_TRI
			AND CTE_EPT.MAX_DATE_EVENEMENT = EPT.DATE_EVENEMENT
			AND EPT.ETAT_PLAN_TRI = 2 -- Etat en cours
		)
	SELECT
		PTR.NO_PLAN_TRI
		, PTR.DATE_CREATION
		, PTR.CODE_PLAN_TRI
		, PTR.LIBELLE
	FROM
		PLAN_TRI PTR
	INNER JOIN
		CTE_PTR
	ON
		CTE_PTR.NO_PLAN_TRI = PTR.NO_PLAN_TRI
Et le problème c'est que nous n'arrivons pas à supprimer le full scan lors de cette requete.
L'index utilisé pour cela est bien celui sur la date mais il y a invariablement un scan...

J'ai également essayé de supprimer le MAX et d'utiliser un row_number, mais le résultat est le même, voire moins performant...

peut on l'éviter ou bien est ce impossible à cause du max ?

Merci pour votre aide