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.

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top