1

SQL Server 2005 データベースに対していくつかのカスタム レポートを作成しています。データベースは、私たちが実行するサードパーティの管理アプリケーションに属しています。私が取得しているデータは、サイトの主な目的に含まれていないため、タイムスタンプ列を除いて、データの大部分はインデックス化されていません。今のところ、関連するテーブルは 1 つだけです。約 7 億行のテーブルです。したがって、50 行のみを返すクエリを実行すると、700mil すべてをポーリングする必要があります。

私はこれをスピードアップしようとしていますが、WHERE 句に追加するすべての列にインデックスを付けたくありません。多くのインデックスを追加すると、速度が大幅に向上するかどうかはわかりません (または、違う?)。したがって、テーブルに新しいインデックスを追加できなかった場合のベスト プラクティスはどうなるか知りたいです。

ストアド プロシージャは最適ではないようです。インデックス付きビューが最良のアイデアでしょうか? 考え?

テーブル スキーマは次のとおりです。

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)

サンプルクエリは次のとおりです。

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

たぶん、クエリは最悪です... 4.5 分で 53 行が返されます。

4

4 に答える 4

0

ここでの最後の解決策は、インデックス付きフィールドに対してクエリを実行し、クエリを実行するアプリケーション内でそれらをフィルタリングすることでした。2つのフィールドには、1つのインデックスに対してクエリを実行し、必要なデータの非常に近い近似値を取得できるほど十分に類似した情報が含まれることになりました。ループバックして、一致しないエンティティを結果リストから削除しました。はるかに少ない時間で済みました!

于 2011-03-17T12:02:51.993 に答える
0

クエリがインデックスを使用していない場合、それは本当に悪いことです。すべての列にインデックスは必要ありませんが、右側の列にはインデックスが必要です。TimeOfEvent が既にインデックス化されていることを考えると、ニーズに合わない可能性があります。

右側の列は、データの分布によって異なります。最適なインデックスは、おそらく、選択性が最も高いインデックスです (つまり、インデックスのキー値がわかっている場合、返される行数が最も少ない)。最適な選択性を提供する列がわかっている場合は、その列でインデックスを試すことができます。

最適なインデックスを決定するために、SSMS の推定実行プランの表示を使用できます。これは、どのインデックスが使用されるかを確認するのに役立ちます。インデックスを追加したら、クエリを実行し、実行計画で結果を評価できます。もちろん、経過時間を観察することも役に立ちます。

于 2010-11-09T22:28:48.033 に答える
0

二重の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 

これにより、エンジンはテーブルを 1 回通過するだけで集計を行う必要がなくなります。うまくいかない場合は、正しいグループ化を得るために、rownumber の一部で order by と partition by を試してみてください。

于 2010-11-10T00:33:13.920 に答える