J'ai besoin de calculer la durée moyenne d'une de nos procédures stockées en cours d'exécution. Par exemple, la durée (en secondes) de SP est: 1,30,2,5,2,15,35,7,3,4,2,1,2,40
Je dois éliminer les 10 premiers appels (appels rapides) et les 10 derniers appels (appels lents) et calculer la moyenne sur le rest.
Y a-t-il une meilleure approche pour minimiser les pertes de performances, car cela doit se faire sur un énorme set de données de façon régulière?
L'approche que je connais est:
Éliminer les 10% d'loggings les plus fréquents en utilisant la requête suivante, ce qui entraîne deux valeurs (1,1)
SELECT TOP 10 PERCENT WITH TIES value FROM #t order by value asc
le fond 10% donne (35,40),
SELECT TOP 10 PERCENT WITH TIES value FROM #t order by value desc
Après avoir éliminé ces valeurs (1,1,35 & 40), la moyenne va être de 7.
Une option qui fonctionne relativement bien dans mes tests (less de 1 seconde avec 300 000 lignes, jusqu'à 12 secondes avec 10 millions de lignes):
declare @tot int = (select count(*) from #MyData) ; with cte as (select Data, ROW_NUMBER() over (order by data) RN from #MyData) select avg(Data) from cte where rn between @tot/10 and 9*@tot/10
Édité pour assurer une "coupe de cheveux" uniforme
Declare @YourTable table (Seconds int) Insert Into @YourTable values (1),(30),(2),(5),(2),(15),(35),(7),(3),(4),(2),(1),(2),(40) Select AvgSeconds = avg(Seconds) From ( Select * ,Dec1 = NTile(10) over (Order By Seconds) ,Dec2 = NTile(10) over (Order By Seconds Desc) From @YourTable ) A Where Dec1 between 2 and 9 and Dec2 between 2 and 9
Résultats
AvgSeconds 7