简体   繁体   中英

how to avoid sub-query to gain performance

i have a reporting query which have 2 long sub-query

SELECT  r1.code_centre, r1.libelle_centre, r1.id_equipe, r1.equipe, r1.id_file_attente, 
r1.libelle_file_attente,r1.id_date, r1.tranche,   r1.id_granularite_de_periode,r1.granularite, 
r1.ContactsTraites,  r1.ContactsenParcage,   r1.ContactsenComm,  r1.DureeTraitementContacts, 
r1.DureeComm,  r1.DureeParcage,    r2.AgentsConnectes,  r2.DureeConnexion,  r2.DureeTraitementAgents, 
r2.DureePostTraitement   
FROM   
    ( SELECT   cc.id_centre_contact, cc.code_centre, cc.libelle_centre, a.id_equipe, a.equipe, 
    a.id_file_attente, f.libelle_file_attente, a.id_date, g.tranche, g.id_granularite_de_periode, 
    g.granularite,    sum(Nb_Contacts_Traites) as ContactsTraites,    
    sum(Nb_Contacts_en_Parcage) as ContactsenParcage,    
    sum(Nb_Contacts_en_Communication) as ContactsenComm,   
    sum(Duree_Traitement/1000) as DureeTraitementContacts, 
    sum(Duree_Communication  / 1000 + Duree_Conference / 1000 + Duree_Com_Interagent  / 1000) as DureeComm,
    sum(Duree_Parcage/1000) as DureeParcage      
    FROM agr_synthese_activite_media_fa_agent a,  centre_contact cc,   
    direction_contact dc,  granularite_de_periode g, media m,   file_attente f                  
    WHERE   m.id_media = a.id_media                  
    AND cc.id_centre_contact = a.id_centre_contact                  
    AND a.id_direction_contact = dc.id_direction_contact                  
    AND dc.direction_contact ='INCOMING'                  
    AND a.id_file_attente = f.id_file_attente                 
    AND m.media = 'PHONE'                   
    AND  (  ( g.valeur_min = date_format(a.id_date,'%d/%m') and g.granularite = 'Jour')                               
    or ( g.granularite = 'Heure'   and  a.id_th_heure = g.id_granularite_de_periode)         )     
    GROUP by  cc.id_centre_contact, a.id_equipe,   a.id_file_attente,  a.id_date, g.tranche, 
    g.id_granularite_de_periode)     r1,     

    (     
        (SELECT  cc.id_centre_contact,cc.code_centre, cc.libelle_centre, a.id_equipe, a.equipe, 
        a.id_date, g.tranche, g.id_granularite_de_periode,g.granularite,     
        count(distinct a.id_agent) as AgentsConnectes,       
        sum(Duree_Connexion / 1000) as DureeConnexion,    
        sum(Duree_en_Traitement / 1000) as DureeTraitementAgents,   
        sum(Duree_en_PostTraitement / 1000) as DureePostTraitement  
        FROM activite_agent a, centre_contact cc,   granularite_de_periode g    
        WHERE  (   g.valeur_min = date_format(a.id_date,'%d/%m') and g.granularite = 'Jour')                    
        AND cc.id_centre_contact = a.id_centre_contact        
        GROUP BY cc.id_centre_contact,  a.id_equipe,   a.id_date, g.tranche, g.id_granularite_de_periode )  
    UNION       
        (SELECT  cc.id_centre_contact,cc.code_centre, cc.libelle_centre, a.id_equipe, a.equipe,
        a.id_date, g.tranche, g.id_granularite_de_periode,g.granularite,        
        count(distinct a.id_agent) as AgentsConnectes,      
        sum(Duree_Connexion / 1000) as DureeConnexion,    
        sum(Duree_en_Traitement / 1000) as DureeTraitementAgents, 
        sum(Duree_en_PostTraitement / 1000) as DureePostTraitement     
        FROM activite_agent a, centre_contact cc, granularite_de_periode g        
        WHERE   (    g.granularite = 'Heure'         
        AND  a.id_th_heure = g.id_granularite_de_periode)         
        AND cc.id_centre_contact = a.id_centre_contact        
        GROUP BY cc.id_centre_contact,a.id_equipe,  a.id_date, g.tranche, g.id_granularite_de_periode)
    )   r2    

WHERE   r1.id_centre_contact = r2.id_centre_contact   
AND r1.id_equipe = r2.id_equipe    AND r1.id_date  = r2.id_date   
AND r1.tranche = r2.tranche      AND r1.id_granularite_de_periode = r2.id_granularite_de_periode 
GROUP BY r1.id_centre_contact , r1.id_equipe,  r1.id_file_attente,
r1.id_date, r1.tranche, r1.id_granularite_de_periode    
ORDER BY r1.code_centre,  r1.libelle_centre,  r1.equipe,   
r1.libelle_file_attente, r1.id_date, r1.id_granularite_de_periode,r1.tranche

the EXPLAIN shows

| id | select_type  | table | type| possible_keys | key  | key_len | ref| rows  | Extra                                        |
'1', 'PRIMARY', '<derived3>', 'ALL', NULL, NULL, NULL, NULL, '2520', 'Using temporary; Using filesort'
'1', 'PRIMARY', '<derived2>', 'ALL', NULL, NULL, NULL, NULL, '4378', 'Using where; Using join buffer'
'3', 'DERIVED', 'a', 'ALL', 'fk_Activite_Agent_centre_contact', NULL, NULL, NULL, '83433', 'Using temporary; Using filesort'
'3', 'DERIVED', 'g', 'ref', 'Index_granularite,Index_Valeur_min', 'Index_Valeur_min', '23', 'func', '1', 'Using where'
'3', 'DERIVED', 'cc', 'ALL', 'PRIMARY', NULL, NULL, NULL, '6', 'Using where; Using join buffer'
'4', 'UNION', 'g', 'ref', 'PRIMARY,Index_granularite', 'Index_granularite', '23', '', '24', 'Using where; Using temporary; Using filesort'
'4', 'UNION', 'a', 'ref', 'fk_Activite_Agent_centre_contact,fk_activite_agent_TH_heure', 'fk_activite_agent_TH_heure', '5', 'reporting_acd.g.Id_Granularite_de_periode', '2979', 'Using where'
'4', 'UNION', 'cc', 'ALL', 'PRIMARY', NULL, NULL, NULL, '6', 'Using where; Using join buffer'
NULL, 'UNION RESULT', '<union3,4>', 'ALL', NULL, NULL, NULL, NULL, NULL, ''
'2', 'DERIVED', 'g', 'range', 'PRIMARY,Index_granularite,Index_Valeur_min', 'Index_granularite', '23', NULL, '389', 'Using where; Using temporary; Using filesort'
'2', 'DERIVED', 'a', 'ALL', 'fk_agr_synthese_activite_media_fa_agent_centre_contact,fk_agr_synthese_activite_media_fa_agent_direction_contact,fk_agr_synthese_activite_media_fa_agent_file_attente,fk_agr_synthese_activite_media_fa_agent_media,fk_agr_synthese_activite_media_fa_agent_th_heure', NULL, NULL, NULL, '20903', 'Using where; Using join buffer'
'2', 'DERIVED', 'cc', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'reporting_acd.a.Id_Centre_Contact', '1', ''
'2', 'DERIVED', 'f', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'reporting_acd.a.Id_File_Attente', '1', ''
'2', 'DERIVED', 'dc', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'reporting_acd.a.Id_Direction_Contact', '1', 'Using where'
'2', 'DERIVED', 'm', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'reporting_acd.a.Id_Media', '1', 'Using where'

don't know it very clear, but i think is the problem of seems it take full scaning

than i change all the sub-query to views(create view as select sub-query), and the result is the same

thanks for any advice

Subquery and view will most of the time give you same result speed-wise.

If your subquery is not variabe, consider creating table that has same structure as your view, and occasionally do:

truncate table my_table;
insert into my_table select * from my_view;

...to cache your subquery data. If properly indexed, it will marginalize time lost on storing results of subquery in table, if data is not that frequently changed, or at least if you don't need up-to-date information on second-to-second basis.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM