SELECT TOP 1 danneggia le prestazioni della query; c'è un modo accessibile da dba per superare questo?


13

In un'applicazione di produzione (C # parlando con SQL Server 2014 Standard) c'è una query che assomiglia a questa, di seguito. Il più delle volte funziona in millisecondi. Ma di tanto in tanto (per alcuni valori di @Id), impazzisce e richiede circa un minuto. Questo è più lungo del timeout dell'app, quindi l'app non riesce per l'utente.

Nei casi "impazzisce", il set di risultati restituito è correttamente vuoto, come in molti ma non in tutti gli altri casi.

Fortunatamente questo è riproducibile sia negli ambienti di produzione che di sviluppo.

Lo sviluppatore dice che rimuovere "TOP 1" dalla query, quindi assicurarsi che l'app consumi le righe extra del set di risultati, risolve il problema delle prestazioni.

Il pianificatore di query non suggerisce indici quando TOP 1è presente. (in sviluppo).

È in corso la modifica della query e la correzione dell'app. L'implementazione richiede un po 'di tempo.

La mia domanda: esiste un modo accessibile da DBA per ottimizzare o modificare l'istanza di produzione di SQL Server per superare questo problema prima che la modifica dell'app con la nuova query venga implementata?

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg ON apg.person_id = bi.person_id
  JOIN pplan ON pplan.plan_id = sub.plan_id
  JOIN product ON product.product_id = [plan].product_id 
  JOIN product_attribute ON product_attribute.product_id = product.product_id 
 WHERE apg.group_id = @Id
   AND apg.start_date < GETDATE()
   AND (apg.end_date IS NULL OR apg.end_date > GETDATE()) 
   AND (sub.end_date IS NULL OR sub.end_date > GETDATE()) 
   AND product_attribute.attribute_type = 'special feature' 
   AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;

L'hai provato come subquery? Ad esempio, selezionare il primo abbonamento_id da (selezionare [il resto della query senza il top1]
SeanR

Forse qualche "normale" ottimizzazione delle query funzionerebbe? Se gli indici sono abbastanza interessanti, le scansioni scompaiono. È meno invasivo di una guida di piano.
usr

Così fa gli stessi valori di @ID sempre fanno "impazzire"? In tal caso, prova utilizzando uno di questi valori e acquisisci il piano di query effettivo. Questo ti dirà cosa non va. Se i valori "cattivi" non sono coerenti, allora sembra probabile che si tratti di uno sniffing dei parametri (vedere la risposta di @ MartinSmith per la soluzione), oppure di un problema di blocco che coinvolge il modo in cui il client richiede e consuma il set di risultati.
RBarryYoung

Risposte:


12

Se non è possibile modificare la query, è possibile utilizzare una guida di piano.

Prova le prestazioni della query con OPTION (QUERYTRACEON 4138)(avrai bisogno di qualcuno con le sysadminautorizzazioni per provare questo).

Se ciò produce prestazioni soddisfacenti, puoi applicarlo con una guida di piano. Se non produce prestazioni soddisfacenti, prova a trovare un suggerimento. Forse OPTION (HASH JOIN, MERGE JOIN)se il problema è rappresentato da loop nidificati inappropriati. Potrebbe essere necessario ricorrere al USE PLAN N'...'suggerimento.

Una volta che conosci i suggerimenti richiesti, puoi applicarli usando le informazioni qui .


OPTION (QUERYTRACEON 4138)ha fatto il trucco. Grazie. Ora passiamo a ordinare le guide di piano.
O. Jones,

0

per grins provalo
`> è cambiato in> = quindi non esattamente la stessa query

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi 
        ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg 
        ON apg.person_id = bi.person_id 
       AND apg.group_id = @Id
       AND apg.start_date < GETDATE()
       AND isnnull(apg.end_date, GETDATE()) >= GETDATE()             
  JOIN pplan 
        ON pplan.plan_id = sub.plan_id
       AND isnnull(sub.end_date, GETDATE()) >= GETDATE()
  JOIN product 
        ON product.product_id = [plan].product_id 
  JOIN product_attribute 
        ON product_attribute.product_id = product.product_id 
       AND product_attribute.attribute_type = 'special feature' 
       AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;

"La modifica della query e la correzione dell'app sono in corso. L'implementazione richiede del tempo." l'OP è alla ricerca di una soluzione che correggi le prestazioni "così come sono".
Martin Smith,

@MartinSmith E quando eseguono una correzione, questa potrebbe essere una soluzione migliore. Fare in modo che l'app utilizzi le righe extra saranno altre modifiche al programma.
paparazzo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.