workflow
特定のアイテムを格納するために使用される本番環境のデータベース テーブルがあります。テーブルの各レコードは、基本的に特定の日付のアイテムのステータスを表します。
単純化しすぎたテーブル構造は次のようなものです。
ワークフロー表
|-------------|------------|---------|----------------|
| Category | ItemCode | Status | InsertDate |
|-------------|------------|---------|----------------|
| Cat1 | Foo1 | 01 | 2012-01-01 |
|-------------|------------|---------|----------------|
| Cat1 | Foo1 | 02 | 2012-03-02 |
|-------------|------------|---------|----------------|
| Cat1 | Foo1 | 03 | 2012-04-01 |
|-------------|------------|---------|----------------|
| Cat1 | Foo2 | 01 | 2012-04-06 |
|-------------|------------|---------|----------------|
| Cat1 | Foo2 | 02 | 2012-05-07 |
|-------------|------------|---------|----------------|
| Cat1 | Foo2 | 04 | 2012-05-09 |
|-------------|------------|---------|----------------|
| Cat2 | Foo3 | 01 | 2011-02-03 |
|-------------|------------|---------|----------------|
| ... | ... | .. |.... |
|-------------|------------|---------|----------------|
したがって、 2012 年 1月1 日にアイテムFoo1はステータス01に達しました。2012 年 4 月 1 日にステータス03に達しました。
StoredProcedurePR_GetCategoryItemsInformation
は、与えられたものを入力として取り、Category
Workflow テーブルを読み取り、次のような結果を返します。
@入力: Cat1
出力:
|------------------|---------------|------------------|---------------------|
| Category | ItemCode | DateOfFirstRecord| StatusOfLatestRecord|
|------------------|---------------|------------------|---------------------|
| Cat1 | Foo1 | 2012-01-01 | 03 |
| Cat1 | Foo2 | 2012-04-06 | 04 |
が与えられた SPは、ワークフローの最初の行を取得して を読み取り、ワークフローの最後の行を取得して現在の を取得するCategory
必要があります。ItemCode
InsertDate
Status
これは、次のような SP 実装で要約されます。
CREATE PROCEDURE dbo.PR_GetFooItemInformation
@Category CHAR(3)
AS
BEGIN
CREATE TABLE #TabTemp (
Category CHAR(3),
ItemCode CHAR(3),
Status CHAR(2),
InsertDate DATETIME
)
CREATE CLUSTERED INDEX XIE1TabTemp
ON #TabTemp (...)
CREATE NONCLUSTERED INDEX XIE2TabTemp
ON #TabTemp (...)
INSERT INTO #TabTemp
SELECT
Category,
ItemCode,
Status,
InsertDate
FROM Workflow
WHERE (Some rules to cut down the number of rows)
SELECT
T1.Category,
Item.ItemCode,
T1.InsertDate,
T2.Status
FROM
Item
INNER JOIN
#TabTemp as T1 ON Item.ItemCode = Workflow.ItemCode
INNER JOIN
#TabTemp as T2 ON Item.ItemCode = Workflow.ItemCode
WHERE
...
AND
T1.InsertDate= SELECT
MIN(InsertDate)
FROM
#TabTemp as T3
WHERE ..
AND
T2.InsertDate = SELECT
MAX(InsertDate)
FROM
#TabTemp as T4
WHERE ..
SP は長年 (2005 年) 期待どおりに機能していましたが、数か月前にランダムなタイムアウトが発生し始めました。テーブルのレコード数workflow
が増加しているため (2.5M とカウント)、そのパフォーマンスは確実に悪化します* .
テーブルには適切にインデックスが付けられており、その価値のために、SQL 管理スタジオは SP でそれ以上のインデックスを提案しません。
一時テーブルを使用しない同じ SP は、4 倍遅くなります。
この時点で、一時テーブルには、各呼び出しで平均 1.5M の行が取り込まれています。
私の限定されたデータベース管理者の知識によると、この問題は、特定のカテゴリの各項目の最初と最後の行に到達するために計算する必要があるMIN
and関数に関連しています。MAX
ワークフロー テーブルと SP の実装に関するいくつかの詳細を省略しましたが、ここで説明した内容が問題の理解に十分であることを願っています。
最後に質問:
この種のシナリオを処理するための SQL 戦略、または SQL サーバー独自のソリューションを知っていますか?
どのような制限がありますか?
SP は BackOffice 関数で使用され、前処理されたサブセットではなく、すべてのライブ レコードを返す必要があります。
* 私はデータベース管理者ではありません。データベース管理者の 1 人が現在、暗い研究室でこの小さな怪物を研究しています。