Question

Je construis quelques rapports personnalisés contre une base de données SQL Server 2005. La base de données appartient à une 3ème application de gestion du parti, nous courons. Les données que je tire est pas parmi les principaux objectifs du site, de sorte que les données sont en grande partie non indexé, sauf pour la colonne d'horodatage. Pour l'instant, il n'y a qu'une seule table impliquée - une table de quelque 700 millions de lignes. Alors, quand je lance une requête contre qui devrait revenir à seulement 50 lignes, il doit consulter l'ensemble 700mil.

Je cherche à accélérer ce, mais ne veulent pas indexer chaque colonne que j'ajouter à la clause WHERE - Je ne sais pas d'ajouter que de nombreux indices finissent par améliorer beaucoup la vitesse ( ou ai-je tort?). Je suis curieux de ce que la meilleure pratique serait si je ne pouvais pas ajouter de nouveaux index à la table!

La procédure stockée ne semble pas le meilleur ajustement. Une vue indexée pourrait être la meilleure idée? Pensées?

Voici le schéma de la table:

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)

Voici une requête exemple:

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

Peut-être que la requête suce ... il retourne 53 rangs en 4,5 minutes.

Était-ce utile?

La solution 3

La solution finale ici est d'exécuter une requête sur les champs indexés, puis les filtrer dans l'application en cours d'exécution de la requête. Deux champs ont fini contenant des informations suffisamment similaires pour que je puisse interroger contre un index et d'obtenir une approximation très proche des données que je voulais. Je mis en boucle à travers et supprimé toutes les entités qui ne correspondent pas de la liste des résultats. Nous avons pris beaucoup moins de temps!

Autres conseils

Si votre requête n'utilise aucun index ce sera vraiment mauvais. Vous n'avez pas besoin d'un index sur chaque colonne, mais vous voulez un sur la colonne de droite. Étant donné que TimeOfEvent est déjà indexé, il ne peut pas être un grand pour vos besoins.

La colonne de droite va dépendre de la distribution de vos données. Le meilleur indice sera probablement l'indice qui fournit une sélectivité plus élevée (à savoir, lorsque vous connaissez une valeur clé pour l'index, il retourne le plus petit nombre de lignes). Si vous connaissez la colonne qui fournit la meilleure sélectivité, vous pouvez essayer de l'index sur elle.

Pour vous aider à déterminer le meilleur index, vous pouvez utiliser le plan d'exécution d'affichage estimé en SSMS. Cela vous aidera à voir l'index sera utilisé. Après avoir ajouté un index, vous pouvez lancer votre requête et d'évaluer les résultats obtenus avec le plan d'exécution. Et, bien sûr, en observant le temps écoulé vous aidera aussi.

essayer cette méthode en utilisant la double trick 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 

avec ce moteur n'a pas besoin de faire des agrégations juste un seul passage à travers la table. si elle ne cherche pas à jouer avec le travail de l'ordre et par partition par des parties du rownumber pour obtenir des groupes corrects.

Ceci est assez simplette, mais je vais essayer la valeur indexée comme le premier test dans le

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top