0

私はOracleクエリに取り組んでおり、それをより速くする必要があります。アドバイスをいただければ幸いです。

  • データベースは Oracle で、ExaData クラスターで実行されます。
  • Oracle バージョン: Oracle Database 11g Enterprise Edition リリース 11.2.0.3.0 - 64 ビット製品

私は2つのテーブルを持っています。

1) トランザクション: 店舗での購入 - TransactionID

2)TransactionItems:各購入には1..多くのアイテムがあります-TransactionID、ItemID

各テーブルには、次の 2 つのフラグがあります。

  • FlagA: はい/いいえ
  • FlagB: はい/いいえ

クエリは次のことを行う必要があります。

  1. TransactionItem のすべてのレコードに FlagA と FlagB の値を設定します。
  2. TransactionItem の Flags の値に基づいて、Transaction の各行の FlagA と FlagB の値を設定します。

クエリを 4 つのステップに分けました。

  1. TransactionItem のフラグ A の値を設定する
  2. TransactionItem のフラグ B の値を設定する
  3. トランザクションのフラグ A の設定値
  4. トランザクションのフラグ B の設定値

クエリはスムーズに実行されます。ただし、これが問題です。何十億ものトランザクション レコードがあり、各トランザクションには約 7 つのトランザクション アイテムがあります。

現在の速度は次のとおりです。

  • 合計時間: 616 秒 / 10.27 分
  • 毎秒 1,218 トランザクション / 毎分 73,000 トランザクションを処理

各ステップの処理時間を追跡しました。

  1. TransactionItem のフラグ A の値を設定する

    • 4分52秒
  2. TransactionItem のフラグ B の値を設定する

    • 3分26秒
  3. トランザクションのフラグ A の設定値

    • 1分6秒
  4. トランザクションのフラグ B の設定値

    • 0分51秒

以下は私の完全なクエリです。他に使用したテーブルはこちら

製品

  • 各 TransactionItem には ProductId があります。 各製品には ProductCode があります。
  • 1 つの製品コードには多くの製品があります

フラグ製品コード

  1. FlagA として分類される ProductCodes のリストを含む 1 つの列

フラグB製品コード

  1. FlagB として分類される ProductCodes のリストを含む 1 つの列

取引支払

  1. これは、各トランザクションの支払いの詳細を含むファクト テーブルです。

Payment_Dim

  1. PaymentID の TransactionPayment へのリンク
  2. これは、FlagB が Payment_Dim.PaymentName に基づいて設定されているために必要です。

私はこれらのインデックスを持っています:

トランザクション 1.TransactionID

TransactionItems 1.TransactionID 2.ProductID

製品 1. 製品 ID 2. 製品コード

FlagAproductCodes 1. ProductCode

FlagBproductCodes 1. ProductCode

支払い 1. PaymentID 2. PaymentCode 3. Payment_Name

助けてくれて本当にありがとう、ありがとう

-- 1.   Set value of FlagA for TransactionItem

Update
          TransactionItems  Item

Set FlagA = 
      (
          Select 
                    Case 


                    When  
                              Item.FlagA_Qty = 0 Then 'N' -- this is the quantity of items purchased that fall into the FlagA category

                    When 
                              FlagA.ProductCode Is Null Then 'N'  

                    Else
                               'Y'

                    End 

          From  
                    Product Prod 
                    Left Join 
                              FlagAproductCodes FlagA 
                                        On Product.ProductCode = FlagA.ProductCode   


          Where  
Product.Prod_Id = Item.Prod_Id                    

        )
;



-- 2.  Set value of FlagB for TransactionItem

Update TransactionItems

Set  FlagB = 'Y'

Where ItemID In 
          (
          Select 
                    Trans_Items.ItemID
          From 
                    TransactionItems Trans_Items
                    Inner Join Product Prod 
                              On Trans_Items.Prod_Id = Product.Prod_Id 
                    Inner Join FlagBproductCodes FlagB 

                              On Product.ProductCode = FlagB.ProductCode
          Where 
                    (
                              Trans_Items.Gov_FlagA_Qty < Trans_Items.Item_Qty
                    ) 
                    AND 
                    (
                              Exists 
                              (Select Transaction_Payment_Fid 
                              From TransactionPayment Trans_Pay

                                        Inner Join Warehouse.Payment_Dim Pay_Dim 
                                                  On Trans_Pay.Payment_Id = Pay_Dim.Payment_Id
                              Where 
                                        Transaction_Fid = Trans_Items.Transaction_Fid 
                                        And Upper(Pay_Dim.Payment_Name) Like '%ABC%'
                              )
                    )
          )          
; 
Update TransactionItems
Set FlagB = 'N'
Where FlagB Is Null;






-- 3: Set FlagA for Transactions


Update
          Transactions  

Set 
          Gov_FlagA_Flag =
                    Case When Exists 
                              (Select ItemID 
                              From TransactionItems Item 
                              Where Item.Transaction_Fid = Transactions.Transaction_Fid 
                              and gov_FlagA_flag = 'Y') 
                              Then 'Y'
                    Else 'N'
                    End
;


-- 4: Set FlagB for Transactions


Update
          Transactions  

Set 
          FlagB =
                    Case When Exists 
                              (Select ItemID 
                              From TransactionItems Item 
                              Where Item.Transaction_Fid = Transactions.Transaction_Fid 
                              And FlagB = 'Y') 
                              Then 'Y'
                    Else 'N'
                    End
;
4

3 に答える 3

0

ガイダンスに本当に感謝しています - 本当に役に立ちました!

並列を有効にすると、大きな違いが生まれました!

ALTER SESSION ENABLE PARALLEL DML;

ご協力ありがとうございました

于 2014-09-02T15:27:05.607 に答える
0

並列実行について調べる必要がありますが、これはおそらく広すぎるトピックであり、ここで完全に調べることはできません。(そして、私はそれについて多くを語る資格がありません)。

当面は、各テーブルを 1 回だけ更新し、偶発的なルックアップの数を減らすことで、ある程度のメリットが得られる可能性があります。これはテストされていませんが、たとえば、TransactionItems に対する 3 つの更新と同じロジックをカバーしていると思います。

merge into TransactionItems TI
using (
  select P.Prod_ID,
    case when FAPC.ProductCode is null then 'N' else 'Y' end as FlagA,
    case when FBPC.ProductCode is null then 'N' else 'Y' end as FlagB
  from Product P
  left join FlagAproductCodes FAPC on FAPC.ProductCode = P.ProductCode
  left join FlagAproductCodes FBPC on FBPC.ProductCode = P.ProductCode
) temp
on (temp.Prod_id = TI.Prod_ID)
when matched then
update set TI.FlagA = case when temp.FlagA = 'Y' and TI.FlagA_Qty != 0
    then 'Y' else 'N' end,
  TI.FlagB = case when TI.FlagA_Qty < TI.Item_Qty
    and exists (
      select Transaction_Payment_Fid 
      from TransactionPayment TP
      join Payment_Dim PD on TP.Payment_Id = PD.Payment_Id
      where TP.Transaction_Fid = TI.Transaction_Fid 
      and upper(PD.Payment_Name) Like '%ABC%'
    ) then 'Y' else 'N' end
/

更新可能なビューを作成することをお勧めします。しかし、その量のデータでは、まだ長い時間がかかります。

これも役に立つかもしれません

于 2014-08-22T16:29:35.357 に答える