我正在处理一个 Oracle 查询,我非常需要让它更快。我将不胜感激任何建议。
- 数据库是 Oracle,在 ExaData 集群上运行。
- Oracle 版本:Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
我有两张桌子。
1) 交易:在商店购买 - TransactionID
2) TransactionItems:每次购买有 1..many items - TransactionID, ItemID
在每个表中,有两个标志:
- 标志A:是/否
- 标志B:是/否
查询需要:
- 为 TransactionItem 中的每条记录设置 FlagA 和 FlagB 的值。
- 根据 TransactionItem 中 Flags 的值,为 Transaction 中的每一行设置 FlagA 和 FlagB 的值
我已将查询分为 4 个步骤。
- 为 TransactionItem 设置标志 A 的值
- 为 TransactionItem 设置标志 B 的值
- 为事务设置标志 A 的值
- 为事务设置标志 B 的值
查询运行顺利。然而,这就是问题所在。有数十亿条Transaction记录,每个Transaction大约有7个Transaction Item。
这是它现在的速度:
- 总时间:616 秒 / 10.27 分钟
- 每秒处理 1,218 个事务/每分钟 73,000 个事务
我跟踪了每个步骤的处理时间:
为 TransactionItem 设置标志 A 的值
- 4分52秒
为 TransactionItem 设置标志 B 的值
- 3分26秒
为事务设置标志 A 的值
- 1分6秒
为事务设置标志 B 的值
- 0 分 51 秒
以下是我的完整查询。这是使用的其他表
产品
- 每个 TransactionItem 都有一个 ProductId 每个产品都有一个 ProductCode。
- 一个产品代码有多个产品
标记AproductCodes
- 包含分类为 FlagA 的 ProductCode 列表的单列
标记B产品代码
- 包含分类为 FlagB 的 ProductCode 列表的单列
交易支付
- 这是一个包含每笔交易的付款详情的事实表
Payment_Dim
- PaymentID 上的 TransactionPayment 链接
- 这是必需的,因为 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
;