Oracle在这里。我有以下表格:
[orders]
===
order_id : integer constraint pk_orders primary key using index
order_name : varchar2(40 char)
order_ordered_by : integer constraint fk_shoppers references accounts
order_total : number(10,2) not null
order_status : char not null
[line_items]
===
line_item_id : integer constraint pk_line_items primary key using index
order_id : integer not null constraint fk_line_items_orders references orders on delete cascade
product_id : integer not null constraint fk_line_items_products references products
line_item_quantity : integer not null
[products]
===
product_id : integer constraint pk_products primary key using index
product_name : varchar2(40 char)
product_category : varchar2(10 char)
product_available_on : date
我试图编写一个查询来更新订单并将其状态设置为“ ORDERED”,其中:
orders.order_status
当前处于“待处理”状态;和products.product_category
当前为“ COFFEE”;和products.product_available_on
当前小于或等于当前时间(现在)到目前为止我最大的努力能成功并完成工作:
UPDATE orders
SET status = 'ORDERED'
WHERE order_id IN (
SELECT DISTINCT orders.order_id
FROM orders
INNER JOIN line_items ON line_items.orderId = orders.order_id
INNER JOIN products ON line_items.product_id = products.product_id
WHERE
orders.status = 'PENDING' AND
products.product_category = 'COFFEE' AND
products.product_available_on <= CURRENT_DATE
);
同样,此确实有效,但是它相当慢,所以我尝试查看是否有一种方法可以在不使用{{1 }}条件(我在多个地方读过IN
可能导致Oracle性能问题)。没有IN
,有什么方法可以完成重写此查询,以便我可以比较性能吗?
请注意::在我的特定用例中,更改表(调整其字段,添加约束/索引/任何内容)是不可能的!
答案 0 :(得分:3)
我会开始:
UPDATE orders o
SET o.status = 'ORDERED'
WHERE o.status = 'PENDING'
AND EXISTS ( SELECT 'line for available coffee'
FROM line_items li
INNER JOIN products p ON p.product_id = li.product_id
WHERE li.order_id = o.order_id
AND p.product_category = 'COFFEE'
AND p.product_available_on <= SYSDATE );
由于某些原因,这比您发布的查询要好。
ORDERS
表一次。 EXISTS
允许
Oracle停止在相关子查询中查找行之一
找到一个。 order_status = 'PENDING'
条件移动到
主UPDATE
,使优化程序更容易实现
它可以使用order_status
上的索引。如果您没有关于订单状态的索引,请考虑一个。确保您使用直方图收集统计信息(如今这通常会自动发生,具体取决于您所使用的Oracle版本)。
为什么直方图很重要?因为您的order_status
值很可能会偏斜(即分布不均匀)。就是说,人们会期望状态为“已关闭”或“已下订单”或“处于保留状态”的许多订单(正在补货...),因此,相对少部分订单的状态为“待处理”。如果没有直方图,Oracle将看到的只有一个具有1,000,000个值和4个不同值的索引-Oracle不太可能使用这样的索引。直方图为它提供了额外的信息,以了解如果您想要“已平仓”的订单,它是一个不好的索引;但是如果您要“待定”订单,那是一个很好的订单。