Sql 需要根据解释计划加速我的更新查询

Sql 需要根据解释计划加速我的更新查询,sql,oracle,indexing,sql-execution-plan,Sql,Oracle,Indexing,Sql Execution Plan,我正在使用一个临时表更新我的表数据,这需要很长时间,但仍然没有完成。因此,我收集了一份关于查询的解释计划。有人能告诉我如何优化查询或在查询上建立索引吗 查询: 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.inve

我正在使用一个临时表更新我的表数据,这需要很长时间,但仍然没有完成。因此,我收集了一份关于查询的解释计划。有人能告诉我如何优化查询或在查询上建立索引吗

查询:

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;
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;
你有问题。为什么要为
库存项目id
创建类型错误的临时表?这可能会减慢任何访问速度。因此,让我们先修复表,然后进行更新:

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\u系统项目\u b\u temp
记录,而不是对
w\u产品\u d
中的每一行反复读取它们

此外,您的表看起来像是Oracle e-BS环境的一部分。在这种环境下的
MTL\u系统\u ITEMS\u B
中,
INVENTORY\u ITEM\u ID
ORGANIZATION\u ID
列是
NUMBER
。您似乎在表中使用了
VARCHAR2
。每当您在查询中不使用正确的数据类型时,都会带来性能问题,因为Oracle必须隐式转换为正确的数据类型,这样做会失去对列使用索引的能力。因此,请确保您的查询根据每列的数据类型正确处理每列。(例如,如果列是
数字
请使用
列_X=123
而不是
列_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...

如果我是你,我会考虑在WiWorkTytd中添加一个索引(整合式ID,CREATEDION ONDT)。我已经看到,如果将此类更新更改为相应的
MERGE
语句,它们的更新速度会快得多。如果您正在检查
created\u on\u dt,则不会忽略created\u dt上的索引,因为您正在检查的
created\u on\u dt为null,并且该索引中永远不会存储空值。这就是为什么我建议在(integration\u id,created\u on\u dt)上创建索引的原因,无论如何。太好了!我错过了字符转换。我从来不知道这会导致开销。我正在添加更新的解释和查询。你认为更新查询可以改进吗,因为它仍然预计在40分钟内完成。@Boneist你想让我在这三个方面创建索引吗:更好的库存项目id、组织id、创建数据在TEMP表上的e?和在CREATED_on_DT上忽略索引?继续在TEMP表上创建索引,但是关于w_product_d表上的索引,我会确保您在索引中包括第二列,以及CREATED_on_DT。如果您没有,那么您在w_DT上创建的空索引将不会存储在索引中(因为如果普通btree索引中的所有列都为空,则该行不会存储在索引中)。根据其他查询使用w_product_d表的情况,在(integration_id,created_on_dt)上创建索引可能有意义,或者如果该索引处于打开状态(created_on_dt,integration_id),您可能会看到此查询的改进 instead@Boneist在w_product_d表上创建索引后,使用组合(在w_dt上创建索引,集成id)解释更新过程的计划是00:38:00。这是我能做到的最好的了吗?或者还有什么可以做的吗?从110:06:25到00:38:28这真的是一个很大的改进!!!谢谢McPeak。我会遵循这一点!只有在为Oracle定义了足够的约束以确保
w_product_d
在隐式视图中保留了密钥的情况下。