0

正常に機能する更新ステートメントがありますが、完了するまでに非常に長い時間がかかります。

1つのテーブルで約150行を更新し、ビューから数万行を公開しています。プロセスを高速化するために、PartitionBy句を使用することをお勧めします。

私はPartitionByステートメントにあまり精通していませんが、周りを見回しており、比較できる数値を持つフィールドを使用する必要があると思います。

これは正しいです?または、大きなテーブルを他のものでパーティション化できますか?

その場合、私は大きな表の何を使用できるかで苦労しています。表は次のように構成されています。

IDのタイプはNUMBERで、特定のアイテムの一意のIDを作成します。Start_Dateには日付タイプがあり、IDが有効な場合の開始を示します。終了日には日付タイプがあり、IDが無効になる終了時刻を示します。ID_TypeはNVARCHAR2(30)であり、使用している識別子のタイプを示します。ID_Type2はNVARCHAR2(30)であり、使用している識別子のsub_typeを示します。識別子はNVARCHAR2(30)であり、任意の1つのIDを1つ以上の識別子にマップできます。

たとえば、-View_ID

ID | Start_Date | End_Date   | ID_Type1| ID_Type2 | Identifier
1  | 2012-01-01 | NULL       | Primary | Tertiary | xyz1
1  | 2012-01-01 | NULL       | Second  | Alpha    | abc2
2  | 2012-01-01 | 2012-01-31 | Primary | Tertiary | ghv2
2  | 2012-02-01 | NULL       | Second  | Alpha    | mno4

IDが日付で有効であるという条項がある限り、このビューのIDフィールドでパーティション化することは可能でしょうか?

updateステートメントは、いくつかの可能な識別子とID_Type1のいずれかを選択しますが、非常に基本的なものです。

UPDATE Temp_Table t set ID = 
(SELECT DISTINCT ID FROM View_ID v
 WHERE inDate BETWEEN Start_Date and End_Date
 AND v.Identifier = (NVL(t.ID1, NVL(t.ID2, t.ID3)))
 AND v.ID_Type1 in ('Primary','Secondary'));

私の質問のあらゆる側面についてのアドバイスを事前に感謝します。

追加情報***

ゴードンのアドバイスを調査して従った後、私はアップデートを3つのアップデートに変更しました。これにより、全体的な更新プロセスが75%短縮され、1分強から20秒強になりました。これは大きな改善ですが、可能であればプロセスをさらに削減したいと思います。

Partition By句がさらに役立つと思う人はいますか?もしそうなら、この句を更新ステートメントに入れるための正しい方法は何でしょうか。この条項がどのように機能するかを理解しているかどうかは正直わかりません。

SELECTステートメントを使用するUPDATEで1つの値しか選択できない場合、これは次のようなものを機能から除外しますか?

UPDATE Temp_Table t SET t.ID = 
(SELECT DISTINCT ID,
        Row_Number () (OVER PARTITION BY ID_Type1) AS PT1
 FROM View_ID v
 WHERE inDate BETWEEN v.Start_Date and v.End_Date
 AND v.Identifier = t.ID1
 AND PT1.Row_Number = 1 )

*ソリューション**** * ** * ****

以下の両方のレスポンダーからのアドバイスを組み合わせて、パフォーマンスを劇的に向上させました。Gordonから、UPDATEからNVLを削除し、3つの別々のアップデートに変更しました。(私はそれらをケースにまとめたいと思いますが、私の試験はまだ遅かったです。)

Eggiから、私は実際に自分自身にインデックスを付けてWITH句に落ち着くことができるある種のマテリアライズドビューで作業しているように見えました。

UPDATE Temp_Table t set ID = 
(WITH IDs AS (SELECT /*+ materialize */ DISTINCT ID, Identifier FROM View_ID v
 WHERE inDate BETWEEN Start_Date and End_Date
 AND v.Identifier = ID1)
 SELECT g.ID FROM IDs g
 WHERE g.Identifier = t.ID1;

再度、感謝します。

4

2 に答える 2

1

パーティション化の最適なオプションは開始日であるように思われます。これは、常に値があり、クエリの入力パラメータとしても取得されるためです。

まだ行っていない場合は、ID_Type1にビットマップインデックスを追加します。

于 2012-08-08T14:19:08.100 に答える
1

ウィンドウ/分析機能がこの更新にどのように役立つか想像するのは非常に困難です. それらを学ぶことを強くお勧めしますが、この目的のためではありません.

おそらく、提案は、テーブルに使用されるテーブルスペースを分割することでした。これは、通常、ウィンドウ/分析関数を参照する "partition by" ステートメントとは大きく異なることに注意してください。表領域のパーティション化は、パフォーマンスを向上させる可能性があります。ただし、他にも試してみることができます。

あなたの問題は、一時テーブルとビューの間の結合だと思います。おそらく、一時テーブルを作成しています。次の定義を使用して、UsedID などの新しい列を追加する必要があります。

coalesce(t.ID1, t.ID2, t.ID3) as UsedId

更新の「WHERE」句は次のようになります。

WHERE inDate BETWEEN Start_Date and End_Date AND
      v.Identifier = t.UsedId AND
      v.ID_Type1 in ('Primary', 'Secondary')

パフォーマンスの問題は、結合での NVL の使用にあると思われます。これは、最適化戦略を妨げます。

あなたのコメントに応えて。. . 元のクエリには、このバージョンと同じ問題があります。おそらく、必要なロジックは次のとおりです。

WHERE inDate BETWEEN Start_Date and End_Date AND
      v.Identifier in (t.ID1, t.ID2, t.ID3) AND
      v.ID_Type1 in ('Primary', 'Secondary')
于 2012-08-08T14:24:12.387 に答える