Pagina 1 di 3 1 2 3 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 28

Discussione: Ottimizzazione Query

  1. #1

    Ottimizzazione Query

    Ciao a tutti,

    io ho una query che fa delle select annidate....su una vista che ha circa 1500 righe....la query mi ritorna 3 righe....ma il mio problema è che

    1. ci mette circa 15 minuti!
    2. la cpu mi va al 100%!

    la query è questa:


    DECLARE @CODE_PREFIX_CA as VARCHAR(255)
    DECLARE @CODE_PREFIX_CNV as VARCHAR(255)
    DECLARE @CODE_PREFIX_SERSTA as VARCHAR(255)
    DECLARE @CODE_PREFIX_MA as varchar(255)
    ----
    DECLARE @data_ora_da as VARCHAR(255)
    DECLARE @data_ora_a as VARCHAR(255)


    --
    DECLARE @CODE_PREFIX as VARCHAR(255)
    set @CODE_PREFIX = 'H/CL/DI'

    if @CODE_PREFIX = 'H/CL/DI'
    begin
    set @CODE_PREFIX_CA = 'H/CL/DI/CA/%'
    set @CODE_PREFIX_CNV = 'H/CL/DI/CNV/%'
    set @CODE_PREFIX_SERSTA = 'H/CL/DI/SERSTA/%'
    set @CODE_PREFIX_MA = 'H/CL/DI/MA'
    end
    else
    begin
    set @CODE_PREFIX_CA = 'H/CL/PO/CA/%'
    set @CODE_PREFIX_CNV = 'H/CL/PO/CNV/%'
    set @CODE_PREFIX_SERSTA = 'H/CL/PO/SERSTA/%'
    set @CODE_PREFIX_MA = 'H/CL/PO/MA'
    end
    --
    set @data_ora_da = '05/04/2011 01:00:00.000'
    set @data_ora_a = '05/12/2011 23:59:00.000'
    --



    select *, ISNULL(TOT_MI, 0) + ISNULL(TOT_ME, 0)
    from
    ( select distinct qi.user_code as cdc, qi.code_prefix as sede_tecnica, qi.code,
    (select sum(real_con_length)
    from
    export_ore
    where (code_prefix = qi.code_prefix or code_prefix like qi.code_prefix + '/%') and commessa is null
    and (competenza = 'E' or competenza = 'G') and tipo_op = 'interno'

    ) as MI_ELET,

    (select sum(real_con_length)
    from export_ore
    where (code_prefix = qi.code_prefix or code_prefix like qi.code_prefix + '/%') and commessa is null
    and competenza = 'M' and tipo_op = 'interno'

    ) as MI_MEC,

    (select sum(real_con_length)
    from export_ore
    where (code_prefix = qi.code_prefix or code_prefix like qi.code_prefix + '/%') and commessa is null
    and tipo_op = 'interno'

    ) as TOT_MI,
    (select sum(real_con_length)
    from export_ore
    where (code_prefix = qi.code_prefix or code_prefix like qi.code_prefix + '/%') and commessa is null
    and tipo_op = 'esterno'

    ) as TOT_ME

    FROM
    (select user_code, code_prefix, code, real_con_length, DATA_AVANZAMENTO,
    [description], tipo_op, commessa, competenza
    from export_ore where (code_prefix like @CODE_PREFIX_CA or code_prefix like @CODE_PREFIX_CNV
    or code_prefix like @CODE_PREFIX_SERSTA or code_prefix = @CODE_PREFIX_MA)

    OR description like 'cdc%'

    and commessa is null
    ) qi
    ) qe
    where qe.tot_mi is not null or qe.tot_me is not null
    order by qe.sede_tecnica


    c'è un modo per ottimizzare sia i tempi di esecuzione che l'impiego della cpu???

    grazie

  2. #2
    prova ad usare il comando EXPLAIN e vedere se e come usa gli indici
    www.contabilitafacile.it

  3. #3
    ciao,

    no non usa nessun indice.....

  4. #4
    allora crea degli indici
    fai un pò di esperimenti con explain e magicamente (si fa per dire)
    le query saranno più veloci...
    www.contabilitafacile.it

  5. #5
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    è fatta davvero "male", sia perchè contiene operatori OR , sia perchè ha dei like, sia perchè vuol fare "in un colpo solo" troppe cose.
    - così en passant le parentesi per le precedenze le metterei -
    ---
    Detto questo la risposta è "non si può dire",
    finquando non posti le strutture delle tabelle, con relative cardinalità, e magari pure una stima della selettività di eventuali indici usati nelle condizioni.

    Conviene fare un passo alla volta (divide-et-impera)
    ---
    partiamo da qui

    codice:
     (select sum(real_con_length)
     from 
     export_ore 
     where (code_prefix = qi.code_prefix or code_prefix like qi.code_prefix + '/%') and commessa is null
     and (competenza = 'E' or competenza = 'G') and tipo_op = 'interno'
    
     ) as MI_ELET,
    Metti la struttura di export_ore, indica quanto è grande,
    metti il count dei distinct code_prefix e competenza,
    oltre a tipo_op.
    E magari conta pure commessa is null

  6. #6
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    Originariamente inviato da Fumocamel
    allora crea degli indici
    fai un pò di esperimenti con explain e magicamente (si fa per dire)
    le query saranno più veloci...
    la strada può essere giusta, ma bisogna un pochino ragionarci sopra, perchè non è detto che gli indici migliorino sempre e comunque le prestazioni.
    E poi vanno scelti oculatamente.

  7. #7
    franzauker cosa non ti convince in questo pezzo di query?

    (select sum(real_con_length)
    from
    export_ore
    where (code_prefix = qi.code_prefix or code_prefix like qi.code_prefix + '/%') and commessa is null
    and (competenza = 'E' or competenza = 'G') and tipo_op = 'interno'

    ) as MI_ELET,

  8. #8
    questa è la vista export_ore...ora la sto usando con una where condition per limitare ulteriormente i dati.....ma non cambia molto.... cmq....mi andrebbe bene anche lasciare la condizione sulla vista....

    questa vista mi ritorna 1146 righe..non motle direi...cmq ci mette una vita!

    SELECT TOP (100) PERCENT f.USER_CODE, f.CODE_PREFIX, f.CODE, o.REAL_CON_LENGTH, o.REAL_CON_COST, o.TIPO_OP, sp.NAME,
    o.DATA_AVANZAMENTO, w.ID_FL, w.ID_WO, s.ID_OP, w.ID_PRJ, p.NAME AS COMMESSA, s.COMPETENZA, p.CODE AS COD_COMMESSA,
    f.DESCRIPTION, p.ID_PRJ AS ID_COMMESSA
    FROM dbo.WORK_ORDER AS w INNER JOIN
    dbo.OPE_WO_NEW AS o ON w.ID_WO = o.ID_WO INNER JOIN
    dbo.FL AS f ON w.ID_FL = f.ID_FL INNER JOIN
    dbo.SYS_USER AS s ON o.ID_OP = s.ID_OP LEFT OUTER JOIN
    dbo.PROJECT AS p ON w.ID_PRJ = p.ID_PRJ LEFT OUTER JOIN
    dbo.SUPPLIER AS sp ON s.ID_SUP = sp.ID_SUP

    WHERE (CONVERT(datetime, REPLACE(o.DATA_AVANZAMENTO, '.', ':'), 3) BETWEEN '05/01/2011 01:00:00.000' AND '05/31/2011 01:00:00.000') OR
    (o.DATA_AVANZAMENTO IS NULL)
    ORDER BY w.ID_WO DESC

    se faccio una select distinct code_prefix mi ritorna 1146...
    i tipo_op sono 2....interno e esterno
    le possibili competenze sono 3...
    invece le righe con commessa a null sono 1085....

  9. #9
    Utente di HTML.it
    Registrato dal
    Jan 2011
    Messaggi
    1,469
    Originariamente inviato da ttttttttttttttt
    franzauker cosa non ti convince in questo pezzo di query?

    (select sum(real_con_length)
    from
    export_ore
    where (code_prefix = qi.code_prefix or code_prefix like qi.code_prefix + '/%') and commessa is null
    and (competenza = 'E' or competenza = 'G') and tipo_op = 'interno'

    ) as MI_ELET,
    Per ordine.
    Quella è un'interrogazione ripetuta N volte, di "male" ha che la funzione sum richiede la scansione di tutte le righe rimaste dopo la selezione; le condizioni di selezione sono in parte buone e in parte non così buone.
    Quelle "buone" sono le = qualcosa, nel qual caso un indice può essere utile.

    Lo è, però, se il numero di righe che viene riportato è bassa, << # totale (selettività elevata).
    i tipo_op sono 2....interno e esterno
    Ad esempio non è molto significativo: è importante ad esempio se "interno" sono l'1% (o viceversa).
    Se sono 50-50 invece l'indice, quasi certamente, non ti serve.
    - per inciso se ha solo 2 valori scegli quello con cardinalità minore e nel filtro ci metti =X oppure NOT = X, invece di =Y)

    ---
    Da quanto ho capito fai un gran mischione per un'interrogazione banale.
    Fossi in te inizierei a considerare la possibilità di "spezzarle" lato applicazione.

    Perchè quella vista (pensavo fosse una tabella) richiede una caterva di join, ed è quindi ontologicamente lenta
    ---
    Riassumendo: se non misuri non saprai mai cosa succede.

    Prima domanda: quanto impieghi a generare le varie versioni dell'export_ore? (è facile, ti basta prendere le query singole e misurarne il tempo).

    Seconda domanda: perchè non ti fai una vista "furba", ossia nella quale ci metti il "minimo comune denominatore" dei WHERE con cui poi la filtrerai?

  10. #10
    Dunque,

    il problema è che quella vista è solo il punto di partenza......da quella prendo i dati e costruisco un'altra tabella con altre colonne (per esempio la colonna NAME in questa vista contiene i nomi delle colonne nell'export finale....quindi alcuni dati vengono traslati in orizzontale)

    il tutto gira in circa mezz'ora.....ma è troppo....e poi sopratutto mi manda la CPU al 100%
    (faccio un'altra domanda: non è possibile dedicare al max un tot di CPU per una determinata procedura?)

    cosa intendi quando dici?
    non ti fai una vista "furba", ossia nella quale ci metti il "minimo comune denominatore" dei WHERE con cui poi la filtrerai?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.