Requête les performances et joindre des conseils, le coût du plan et la durée
-
31-10-2019 - |
Question
Avoir du mal à identifier pourquoi la durée d'une requête diminuerait lors de l'utilisation OPTION (HASH JOIN)
ou OPTION (MERGE JOIN)
, bien que le coût du plan augmente.
Arrière plan
J'ai une base de données de rapport utilisant le schéma d'étoiles traditionnel (tables de dimension / fait). SQL est généré par ORM dans l'outil BI. J'ai une certaine flexibilité avec le SQL généré en termes d'ajout de conseils d'optimiseur, mais c'est tout (pas de refactorisation de requête, etc.).
Problème
Lorsque la requête ci-dessous est exécutée sans indice d'optimiseur, la durée moyenne est d'environ 90 secondes et le coût du sous-arbre estimé est d'environ 2,9. Lorsqu'il est exécuté avec le OPTION (MERGE JOIN)
ou OPTION (HASH JOIN)
Des conseils, la durée moyenne est d'environ 3 secondes, mais le coût estimé du sous-arbre est d'environ 4,9.
J'ai vérifié que les statistiques sur les tables affectées sont à jour en utilisant UPDATE STATISTICS <schema>.<table> WITH FULLSCAN;
. Des index ont également été ajoutés sur la base de recommandations d'optimiseur.
Voici la requête (oui, c'est moche, voir ORM Commentaire ci-dessus):
SELECT a11.trans_00_key TRANS_00_KEY,
a11.region_id REGION_ID,
Max(a15.region_cd) REGION_CD,
a11.state_id STATE_ID,
Max(a13.district_cd) DISTRICT_CD,
a12.cntrct_nbr CNTRCT_NBR,
a11.proj_nbr PROJ_NBR,
Max(a11.proj_nbr) PROJ_NBR0,
CONVERT(DATETIME, CONVERT(VARCHAR(10), (a12.sys_date_yr + '-' + a12.sys_date_mon + '-01'), 101)) CustCol_5,
a12.proj_ctgry_nbr PROJ_CTGRY_NBR,
a11.type_of_work TYPE_OF_WORK,
a11.funct_rng FUNCT_RNG,
Isnull(a11.fis_id, -1) FIS_ID,
Max(Isnull(a14.fis_dscr, 'Blank')) FIS_DSCR,
CASE WHEN a12.bid_amount > 1 THEN a12.bid_amount ELSE a12.eng_est_amt END CustCol_7,
Sum(a11.est_amt) WJXBFS1,
(Sum(a11.ltd_amt) - (Sum(a11.ltd_ind_bill_cst) + Sum(a11.ltd_ind_non_bill_cst))) WJXBFS2,
Sum(a11.ltd_cost_cntrct) WJXBFS3,
((Sum(a11.ltd_amt) - (Sum(a11.ltd_ind_bill_cst) + Sum(a11.ltd_ind_non_bill_cst))) - Sum(a11.ltd_cost_cntrct)) WJXBFS4,
(Sum(a11.est_amt) - (Sum(a11.ltd_amt) - (Sum(a11.ltd_ind_bill_cst) + Sum(a11.ltd_ind_non_bill_cst)))) WJXBFS5
FROM sys_trans_detail_fact a11
JOIN sys_trans_hdr_fact a12
ON (a11.proj_nbr = a12.proj_nbr AND
a11.trans_00_key = a12.trans_00_key AND
a11.state_id = a12.state_id)
JOIN district_lkp a13
ON (a11.state_id = a13.state_id)
JOIN fis_lkp a14
ON (Isnull(a11.fis_id, -1) = Isnull(a14.fis_id, -1))
JOIN region_lkp a15
ON (a11.region_id = a15.region_id)
WHERE (((a11.trans_00_key)
IN (SELECT r12.trans_00_key
FROM sys_trans_detail_fact r12
WHERE r12.fund_src_name_id IN (3, 7, 5)))
AND a11.fund_src_name_id IN (6, 8, 2, 3, 7, 5, 4)
AND a11.state_id IN (8, 4, 19, 14, 20, 23, 17, 25, 16, 18, 24, 2, 12, 22, 5, 11, 6, 1, 21, 7, 15, 10, 9, 3, 13, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36)
AND a11.status_id = 1
AND a11.extract_dttm IN (CONVERT(DATETIME, '2012-09-01 00:00:00', 120))
AND a11.cost_cat_id IN (10, 4))
GROUP BY a11.trans_00_key,
a11.region_id,
a11.state_id,
a12.cntrct_nbr,
a11.proj_nbr,
CONVERT(DATETIME, CONVERT(VARCHAR(10), (a12.sys_date_yr + '-' + a12.sys_date_mon + '-01'), 101)),
a12.proj_ctgry_nbr,
a11.type_of_work,
a11.funct_rng,
Isnull(a11.fis_id, -1),
CASE WHEN a12.bid_amount > 1 THEN a12.bid_amount ELSE a12.eng_est_amt END
Plan d'exécution réel sans indice
Je suis confus quant à la raison pour laquelle le plan montre 572 millions de lignes réelles pour l'indice recherché en rouge.
Plan d'exécution réel en utilisant OPTION (HASH JOIN)
indice
J'ai lu que les conseils d'optimiseur sont un dernier recours après la vérification des indices appropriés appliqués et que les statistiques sont vérifiées à jour. Dans ce cas, SQL Server semble choisir le meilleur plan en fonction du coût, mais il y a une pénalité significative (environ 87 secondes) en termes de durée de la requête. Cela ressemble-t-il à un cas où l'indice Optimizer doit être utilisé? Sinon, quels autres articles dois-je vérifier pour s'assurer que l'optimiseur choisit le meilleur plan de coût et de durée?
Pas de solution correcte