需要根据 EXPLAIN PLAN 加快我的 UPDATE QUERY

Need to speed up my UPDATE QUERY based on the EXPLAIN PLAN

我正在使用临时 table 更新我的 table 数据,这需要很长时间,但仍未完成。所以我收集了一个关于查询的解释计划。有人可以建议我如何调整查询或在其上构建索引。

查询:

UPDATE w_product_d A
SET A.CREATED_ON_DT = (SELECT min(B.creation_date)
                       FROM mtl_system_items_b_temp B
                       WHERE  to_char(B.inventory_item_id) = A.integration_id
                       and B.organization_id IN ('102'))
where A.CREATED_ON_DT is null;

说明计划:

Plan hash value: 1520882583

-----------------------------------------------------------------------------------------------
| Id  | Operation           | Name                    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT    |                         | 47998 |   984K|    33M  (2)|110:06:25 |
|   1 |  UPDATE             | W_PRODUCT_D             |       |       |            |          |
|*  2 |   TABLE ACCESS FULL | W_PRODUCT_D             | 47998 |   984K|  9454   (1)| 00:01:54 |
|   3 |   SORT AGGREGATE    |                         |     1 |    35 |            |          |
|*  4 |    TABLE ACCESS FULL| MTL_SYSTEM_ITEMS_B_TEMP |  1568 | 54880 |   688   (2)| 00:00:09 |
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("A"."CREATED_ON_DT" IS NULL)
   4 - filter("B"."ORGANIZATION_ID"=102 AND TO_CHAR("B"."INVENTORY_ITEM_ID")=:B1)

Note
-----
   - dynamic sampling used for this statement (level=2)

对于此查询:

UPDATE w_product_d A
    SET A.CREATED_ON_DT = (SELECT min(B.creation_date)
                           FROM mtl_system_items_b_temp B
                           WHERE to_char(B.inventory_item_id) = A.integration_id
                                 and B.organization_id IN ('102'))
    where A.CREATED_ON_DT is null;

你有问题。为什么要为 inventory_item_id 创建类型错误的临时 table?这可能会减慢任何访问速度。所以,让我们先修复 table,然后再进行更新:

alter table mtl_system_items_b_temp
    add better_inventory_item_id varchar2(255);  -- or whatever the right type is

update mtl_system_items_b_temp
    set better_inventory_item_id = to_char(inventory_item_id);

接下来,让我们定义合适的索引:

create index idx_mtl_system_items_b_temp_3 on mtl_system_items_b_temp(better_inventory_item_id, organization_id, creation_date);

最后,w_product_d 上的索引也有帮助:

create index idx_ w_product_d_1 w_product_d(CREATED_ON_DT);

然后,将查询写为:

UPDATE w_product_d p
    SET CREATED_ON_DT = (SELECT min(t.creation_date)
                         FROM mtl_system_items_b_temp t
                         WHERE t.better_nventory_item_id) = p.integration_id and
                               t.organization_id IN ('102')
                        )
    WHERE p.CREATED_ON_DT is null;

尝试 MERGE 语句。它可能会更快,因为它可以一次读取所有 mtl_system_items_b_temp 记录,而不是为 w_product_d.

中的每一行一遍又一遍地读取它们

此外,您的表看起来像是 Oracle e-BS 环境的一部分。在MTL_SYSTEM_ITEMS_B这样的环境中,INVENTORY_ITEM_IDORGANIZATION_ID列是NUMBER。您似乎在表格中使用了 VARCHAR2。每当您在查询中不使用正确的数据类型时,就会引起性能问题,因为 Oracle 必须隐式转换为正确的数据类型,并且这样做会失去在列上使用索引的能力。因此,请确保您的查询根据其数据类型正确处理每一列。 (例如,如果列是 NUMBER,请使用 COLUMN_X = 123 而不是 COLUMN_X = '123'

这是 MERGE 示例:

MERGE INTO w_product_d t
USING ( SELECT to_char(inventory_item_id) inventory_item_id_char, min(creation_date) min_creation_date
        FROM   mtl_system_items_b_temp 
        WHERE  organization_id IN ('102')  -- change this to IN (102) if organization_id is a NUMBER field!
      ) u
ON ( t.integration_id = u.inventory_item_id_char AND t.created_on_dt IS NULL )
WHEN MATCHED THEN UPDATE SET t.created_on_dt = nvl(t.created_on_date, u.min_creation_date)  -- NVL is just in case...