Veloce query SQL per dati non indicizzati
-
30-09-2019 - |
Domanda
Sto costruendo un paio di report personalizzati nei confronti di un database di SQL Server 2005. Il database appartiene a una terza applicazione per la gestione del partito corriamo. I dati sto tirando non è tra gli scopi primari del sito, in modo che il dato è in gran parte non indicizzato ad eccezione della colonna timestamp. Per ora, c'è solo un tavolo in questione - una tabella di circa 700 milioni di righe. Così, quando si esegue una query contro di essa che dovrebbe restituire solo 50 righe, deve interrogare tutti 700mil.
Sto cercando di accelerare questo, ma non si vuole indicizzare ogni colonna che sto aggiungendo la clausola WHERE - non so che aggiungere che molti indici finirà per migliorare la velocità di molto ( o mi sbaglio?). Quindi sono curioso di ciò che la migliore pratica sarebbe se io riuscivo a non aggiungere eventuali nuovi indici al tavolo!
stored procedure non sembra la soluzione migliore. Una vista indicizzata potrebbe essere l'idea migliore? Pensieri?
Ecco lo schema della tabella:
DeviceGuid (PK, uniqueidentifier, not null)
DeviceID (int, not null)
WindowsEventID (PK, int, not null) (indexed)
EventLog (varchar(64), not null)
EventSource (varchar(64), not null)
EventID (int, not null)
Severity (int, not null)
Description (nvarchar(max), not null)
TimeOfEvent (PK, datetime, not null) (indexed)
OccurrenceNbr (int, not null)
Ecco una query di esempio:
SELECT COUNT(*) AS NumOcc, EventID, EventLog, EventSource, Severity, TimeOfEvent, Description
FROM WindowsEvent
WHERE DeviceID='34818'
AND Severity=1
AND TimeOfEvent >= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/10/27 12:00:00 AM')
AND TimeOfEvent <= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/11/3 12:00:00 AM')
AND EventID<>34113
AND EventID<>34114
AND EventID<>34112
AND EventID<>57755
AND EventSource<>'AutoImportSvc.exe'
AND EventLog='Application'
GROUP BY EventID, EventLog, EventSource, Severity, Description
ORDER BY NumOcc DESC
Forse la query fa schifo ... restituisce 53 righe in 4,5 minuti.
Soluzione 3
La soluzione finale è stato qui per eseguire una query i campi indicizzati, quindi filtrare all'interno dell'applicazione eseguire la query. Due campi finito contenente informazioni abbastanza simili che ho potuto interrogare l'uno contro l'indice e ottenere una buona approssimazione dei dati che volevo. I ricollegati tramite e rimosso tutte le entità non corrispondenti dalla lista dei risultati. Ha preso molto meno tempo!
Altri suggerimenti
Se la query non utilizza gli indici che sarà veramente male. Non hai bisogno di un indice su ogni colonna, ma si vorrà uno sulla colonna di destra. Dato che TimeOfEvent è già indicizzato, potrebbe non essere un grande per le vostre esigenze.
La colonna di destra sta andando a dipendere dalla distribuzione dei dati. L'indice migliore sarà probabilmente l'indice che fornisce la più alta selettività (vale a dire, quando si sa che un valore chiave per l'indice che restituisce le righe minor numero). Se si conosce la colonna che fornisce la migliore selettività, si può provare l'indice su di esso.
per aiutare a determinare il miglior indice, è possibile utilizzare il display piano di esecuzione stimato in SSMS. Questo vi aiuterà a vedere quale indice verrà utilizzato. Dopo aver aggiunto un indice, è possibile eseguire la query e valutare i risultati con il piano di esecuzione. E, naturalmente, osservando il tempo trascorso aiuterà anche.
provare questo metodo che utilizza il doppio trucco row_number:
SELECT RN_Desc as NumOcc, *
FROM (
SELECT row_number() Over(partition by EventId order by EventLog, EventSource, Severity, Description) as RN_Asc,
row_number() Over(partition by EventId order by EventLog desc, EventSource desc, Severity desc, Description desc) as RN_Desc,
*
FROM WindowsEvent
WHERE DeviceID='34818'
AND Severity=1
AND TimeOfEvent >= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/10/27 12:00:00 AM')
AND TimeOfEvent <= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/11/3 12:00:00 AM')
AND EventID<>34113
AND EventID<>34114
AND EventID<>34112
AND EventID<>57755
AND EventSource<>'AutoImportSvc.exe'
AND EventLog='Application'
) t
WHERE RN_Asc = 1
ORDER BY NumOcc DESC
con questo motore non ha bisogno di fare qualsiasi aggregazioni solo un unico passaggio attraverso la tabella. se non funziona provare a giocare con l'ordine e la partizione da parti del RowNumber per ottenere raggruppamenti corrette.
Questo è abbastanza ingenuo, ma mi piacerebbe provare il valore indicizzato come il primo test nella