Bonjour,

J'ai une requête SQL qui est lente (13 secondes pour ne rien retourner) et je ne comprend pas du tout pourquoi.

Elle est très moche (évidement, générée par un outil) :
Code sql : 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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
 
declare @p1 as bigint = 1
 
SELECT
        TOP 16 Artikelbez,
        ID               ,
        ID_FI_250
FROM
        TE_ISI_UP
WHERE
        ID_FI_250=@P1
AND     LosKZ    =0
AND     (
                MNO IN(0,6000,8101,8102,9000))
AND     ((
                        TE_ISI_UP.ID_FI=0
                OR      (
                                TE_ISI_UP.ID_FI<>0
                        AND     EXISTS
                                (
                                        SELECT
                                                ID
                                        FROM
                                                TE_ISI_FI
                                        WHERE
                                                TE_ISI_UP.ID_FI=ID
                                        AND     (
                                                        TE_ISI_FI.LosKZ=0
                                                AND     (
                                                                TE_ISI_FI.MandNr IN(0,6000,8101,8102,9000))
                                                AND     (((((
                                                                                                TE_ISI_FI.Fityp =2
                                                                                        OR      TE_ISI_FI.Fityp2=2
                                                                                        OR      TE_ISI_FI.Fityp3=2
                                                                                        OR      TE_ISI_FI.Fityp4=2
                                                                                        OR      TE_ISI_FI.Fityp5=2))
                                                                        OR      (
                                                                                        TE_ISI_FI.Fityp2=2)
                                                                        OR      (
                                                                                        TE_ISI_FI.Fityp3=2)
                                                                        OR      (
                                                                                        TE_ISI_FI.Fityp4=2)
                                                                        OR      (
                                                                                        TE_ISI_FI.Fityp5=2)))
                                                        AND     (
                                                                        EXISTS
                                                                        (
                                                                                SELECT
                                                                                        ID
                                                                                FROM
                                                                                        TE_ISI_SB
                                                                                WHERE
                                                                                        (
                                                                                                TE_ISI_FI.ID=TE_ISI_SB.ID_FI)
                                                                                AND     TE_ISI_SB.LosKZ=0
                                                                                AND     ((
                                                                                                        TE_ISI_SB.FreiL1=0))
                                                                                AND     (
                                                                                                EXISTS
                                                                                                (
                                                                                                        SELECT
                                                                                                                ID
                                                                                                        FROM
                                                                                                                TE_ISI_ID
                                                                                                        WHERE
                                                                                                                TE_ISI_SB.BearbeiterId<>0
                                                                                                        AND     TE_ISI_ID.ID           =TE_ISI_SB.BearbeiterId
                                                                                                        AND     (
                                                                                                                        TE_ISI_ID.Oeffentlich=1
                                                                                                                OR      TE_ISI_ID.MandNr IN(0,6000,8101,8102,9000))
                                                                                                        AND     TE_ISI_ID.LosKZ=0
                                                                                                        AND     (((
                                                                                                                                        TE_ISI_ID.HierarchyCode LIKE '469.1.2.3.%'
                                                                                                                                OR      TE_ISI_ID.HierarchyCode    ='-1')))))))
                                                        OR      ((((
                                                                                                TE_ISI_FI.Fityp !=2
                                                                                        AND     TE_ISI_FI.Fityp2!=2
                                                                                        AND     TE_ISI_FI.Fityp3!=2
                                                                                        AND     TE_ISI_FI.Fityp4!=2
                                                                                        AND     TE_ISI_FI.Fityp5!=2))
                                                                        AND     ((
                                                                                                TE_ISI_FI.Fityp !=0
                                                                                        OR      TE_ISI_FI.Fityp2!=0
                                                                                        OR      TE_ISI_FI.Fityp3!=0
                                                                                        OR      TE_ISI_FI.Fityp4!=0
                                                                                        OR      TE_ISI_FI.Fityp5!=0)))
                                                                OR      ((
                                                                                        TE_ISI_FI.Fityp2!=2)
                                                                        AND     (
                                                                                        TE_ISI_FI.Fityp2!=0))
                                                                OR      ((
                                                                                        TE_ISI_FI.Fityp3!=2)
                                                                        AND     (
                                                                                        TE_ISI_FI.Fityp3!=0))
                                                                OR      ((
                                                                                        TE_ISI_FI.Fityp4!=2)
                                                                        AND     (
                                                                                        TE_ISI_FI.Fityp4!=0))
                                                                OR      ((
                                                                                        TE_ISI_FI.Fityp5!=2)
                                                                        AND     (
                                                                                        TE_ISI_FI.Fityp5!=0))))
                                                AND     (((((
                                                                                                TE_ISI_FI.ID>=4294967296
                                                                                        AND     TE_ISI_FI.ID <8589934592))
                                                                        AND     ((
                                                                                                TE_ISI_FI.ID % CAST(4294967296 AS BIGINT))=426266))
                                                                OR      (
                                                                                TE_ISI_FI.F6013=1)
                                                                OR      ((((
                                                                                                        TE_ISI_FI.Fityp NOT  IN(3,5)
                                                                                                AND     TE_ISI_FI.Fityp2 NOT IN(3,5)
                                                                                                AND     TE_ISI_FI.Fityp3 NOT IN(3,5)
                                                                                                AND     TE_ISI_FI.Fityp4 NOT IN(3,5)
                                                                                                AND     TE_ISI_FI.Fityp5 NOT IN(3,5)))
                                                                                AND     ((
                                                                                                        TE_ISI_FI.Fityp !=0
                                                                                                OR      TE_ISI_FI.Fityp2!=0
                                                                                                OR      TE_ISI_FI.Fityp3!=0
                                                                                                OR      TE_ISI_FI.Fityp4!=0
                                                                                                OR      TE_ISI_FI.Fityp5!=0)))
                                                                        OR      ((
                                                                                                TE_ISI_FI.Fityp2 NOT IN(3,5))
                                                                                AND     (
                                                                                                TE_ISI_FI.Fityp2!=0))
                                                                        OR      ((
                                                                                                TE_ISI_FI.Fityp3 NOT IN(3,5))
                                                                                AND     (
                                                                                                TE_ISI_FI.Fityp3!=0))
                                                                        OR      ((
                                                                                                TE_ISI_FI.Fityp4 NOT IN(3,5))
                                                                                AND     (
                                                                                                TE_ISI_FI.Fityp4!=0))
                                                                        OR      ((
                                                                                                TE_ISI_FI.Fityp5 NOT IN(3,5))
                                                                                AND     (
                                                                                                TE_ISI_FI.Fityp5!=0))))
                                                        OR      (((
                                                                                        TE_ISI_FI.Fityp =3
                                                                                OR      TE_ISI_FI.Fityp2=3
                                                                                OR      TE_ISI_FI.Fityp3=3
                                                                                OR      TE_ISI_FI.Fityp4=3
                                                                                OR      TE_ISI_FI.Fityp5=3))
                                                                OR      (
                                                                                TE_ISI_FI.Fityp2=3)
                                                                OR      (
                                                                                TE_ISI_FI.Fityp3=3)
                                                                OR      (
                                                                                TE_ISI_FI.Fityp4=3)
                                                                OR      (
                                                                                TE_ISI_FI.Fityp5=3))
                                                        AND     (
                                                                        EXISTS
                                                                        (
                                                                                SELECT
                                                                                        ID
                                                                                FROM
                                                                                        TE_ISI_C027
                                                                                WHERE
                                                                                        TE_ISI_C027.ID_FI=TE_ISI_FI.ID
                                                                                AND     (
                                                                                                TE_ISI_C027.MNO IN(0,6000,8101,8102,9000))
                                                                                AND     TE_ISI_C027.DEL=0
                                                                                AND     ((
                                                                                                        TE_ISI_C027.MNO=6000))))
                                                        OR      (((
                                                                                        TE_ISI_FI.Fityp =5
                                                                                OR      TE_ISI_FI.Fityp2=5
                                                                                OR      TE_ISI_FI.Fityp3=5
                                                                                OR      TE_ISI_FI.Fityp4=5
                                                                                OR      TE_ISI_FI.Fityp5=5))
                                                                OR      (
                                                                                TE_ISI_FI.Fityp2=5)
                                                                OR      (
                                                                                TE_ISI_FI.Fityp3=5)
                                                                OR      (
                                                                                TE_ISI_FI.Fityp4=5)
                                                                OR      (
                                                                                TE_ISI_FI.Fityp5=5))
                                                        AND     (
                                                                        EXISTS
                                                                        (
                                                                                SELECT
                                                                                        ID
                                                                                FROM
                                                                                        TE_ISI_C009
                                                                                WHERE
                                                                                        TE_ISI_C009.ID_FI=TE_ISI_FI.ID
                                                                                AND     (
                                                                                                TE_ISI_C009.MNO IN(0,6000,8101,8102,9000))
                                                                                AND     TE_ISI_C009.DEL=0
                                                                                AND     ((
                                                                                                        TE_ISI_C009.MNO=6000)))))))))
        AND     (
                        EXISTS
                        (
                                SELECT
                                        ID
                                FROM
                                        TE_ISI_AU
                                WHERE
                                        TE_ISI_UP.ID_AU<>0
                                AND     TE_ISI_AU.ID    =TE_ISI_UP.ID_AU
                                AND     (
                                                TE_ISI_AU.LosKZ=0
                                        AND     (
                                                        TE_ISI_AU.MNO IN(0,6000,8101,8102,9000))))))
ORDER BY
        AufDat DESC,
        F4018      ,
        Position   ,
        Artikelnr  ,
        (ID_AU % CAST(4294967296 AS BIGINT)) DESC

Pour comprendre ce qui me pose problème on peut la simplifier de la sorte :
Code sql : 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
 
declare @p1 as bigint = 1
 
SELECT
        TOP 16 Artikelbez,
        ID               ,
        ID_FI_250
FROM
        TE_ISI_UP
WHERE
        ID_FI_250=@P1
AND     LosKZ    =0
AND     MNO IN(0,6000,8101,8102,9000)
AND     (1 = 1) /* de toute façon c'est pas cette partie qui change quoi que ce soit */
ORDER BY
        AufDat DESC,
        F4018      ,
        Position   ,
        Artikelnr  ,
        (ID_AU % CAST(4294967296 AS BIGINT)) DESC

Étant donné que j'ai cet index : (conseillé par SSMS)
Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
 
CREATE UNIQUE NONCLUSTERED INDEX [TE_ISI_UP_AF304] ON [dbo].[TE_ISI_UP]
(
	[ID_FI_250] ASC,
	[LosKZ] ASC,
	[ID_AU] ASC,
	[MNO] ASC,
	[ID] ASC
)
INCLUDE([ID_FI],[Position],[Artikelnr],[Artikelbez],[AufDat],[F4018]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Je ne comprends pas comment ça peut être aussi lent puisque ID_FI_250 = 1 n'existe pas.
C'est le premier critère de ma requête, et la première colonne de mon index !

Comment SQL Server peut-il passer 13 secondes à ne pas se rendre compte que la première colonne de l'index ne match pas une valeur cardinale toute bête ?

PS : Evidement, mon index est bien utilisé

Edit : Petite musique de la 4ème dimension... Maintenant la requête est instantanée...