Oracle Sql更新1000万条记录需要4天时间

Oracle Sql更新1000万条记录需要4天时间,oracle,plsql,query-performance,Oracle,Plsql,Query Performance,我想从一个临时表中更新一个数据库表,它有超过1000万条记录。 但我的更新查询执行时间超过4天 1.)我已经为的更新搜索条件创建了索引 “税务”\u“分类账”\u“项目”\u选项卡。根据参与方类型、身份、公司创建的索引。 我的搜索条件是:参与方类型、身份、公司、交货类型\u id 正如下面给定的查询一样,这些列不是表中的键 我相信我不能为索引添加delivery\u type\u id 通过查询更新,如果我将其添加到索引中,性能将最差 2.)临时表标识\发票\信息\ cfv还将返回70000条记

我想从一个临时表中更新一个数据库表,它有超过1000万条记录。 但我的更新查询执行时间超过4天

1.)我已经为的更新搜索条件创建了索引 “税务”\u“分类账”\u“项目”\u选项卡。根据参与方类型、身份、公司创建的索引。 我的搜索条件是:参与方类型、身份、公司、交货类型\u id 正如下面给定的查询一样,这些列不是表中的键

我相信我不能为索引添加delivery\u type\u id 通过查询更新,如果我将其添加到索引中,性能将最差

2.)临时表标识\发票\信息\ cfv还将返回70000条记录 还有

到目前为止,我相信我的更新执行计划成本大约为70000*1000万条记录

如何通过以下更新查询获得性能增强?我只想更新delivery\u type\u id,仅获取列

DECLARE

CURSOR get_records IS
  SELECT i.COMPANY, i.IDENTITY, i.CF$_DELIVERY_TYPE
    FROM identity_invoice_info_cfv i
   WHERE i.PARTY_TYPE_DB = 'CUSTOMER';

BEGIN

  FOR rec_ IN get_records LOOP
  dbms_output.put_line  (sysdate ); 

    UPDATE tax_ledger_item_tab t
       SET t.delivery_type_id = rec_.CF$_DELIVERY_TYPE, t.fetched = 'TRUE'
     WHERE t.party_type = 'CUSTOMER'
       AND t.identity = rec_.IDENTITY
       AND t.company = rec_.COMPANY
       AND t.delivery_type_id IS NULL;

    COMMIT;  

  END LOOP;

 END;

我希望您也可以使用Merge语句来实现这一点。下面是相同的代码。请使用一些样本数据从您这边进行测试,然后继续

  Merge into tax_ledger_item_tab t
  using identity_invoice_info_cfv i
      on (t.party_type ='CUSTOMER' and t.identity=i.IDENTITY 
         and t.company = i.COMPANY  and i.PARTY_TYPE_DB = 'CUSTOMER')
       when matched then
             update set  
              t.delivery_type_id=i.CF$_DELIVERY_TYPE,
              t.fetched = 'TRUE' 
            where t.delivery_type_id IS NULL;
        commit;

使用
MERGE
语句:

Oracle安装程序

CREATE TABLE identity_invoice_info_cfv ( COMPANY, IDENTITY, CF$_DELIVERY_TYPE, PARTY_TYPE_DB ) AS
SELECT 'A', 123, 456, 'CUSTOMER' FROM DUAL;

CREATE TABLE tax_ledger_item_tab ( identity, company, party_type, delivery_type_id, fetched ) AS
SELECT 123, 'A', 'CUSTOMER', CAST( NULL AS NUMBER ), 'FALSE' FROM DUAL;
MERGE INTO tax_ledger_item_tab t
USING identity_invoice_info_cfv i
ON (
    t.identity      = i.identity
AND t.company       = i.COMPANY
AND t.party_type    = 'CUSTOMER'
AND i.PARTY_TYPE_DB = 'CUSTOMER'
)
WHEN MATCHED THEN
  UPDATE
  SET delivery_type_id = i.CF$_DELIVERY_TYPE,
      fetched          = 'TRUE'
  WHERE t.delivery_type_id IS NULL;
SELECT * FROM tax_ledger_item_tab;
IDENTITY | COMPANY | PARTY_TYPE | DELIVERY_TYPE_ID | FETCHED -------: | :------ | :--------- | ---------------: | :------ 123 | A | CUSTOMER | 456 | TRUE 合并

CREATE TABLE identity_invoice_info_cfv ( COMPANY, IDENTITY, CF$_DELIVERY_TYPE, PARTY_TYPE_DB ) AS
SELECT 'A', 123, 456, 'CUSTOMER' FROM DUAL;

CREATE TABLE tax_ledger_item_tab ( identity, company, party_type, delivery_type_id, fetched ) AS
SELECT 123, 'A', 'CUSTOMER', CAST( NULL AS NUMBER ), 'FALSE' FROM DUAL;
MERGE INTO tax_ledger_item_tab t
USING identity_invoice_info_cfv i
ON (
    t.identity      = i.identity
AND t.company       = i.COMPANY
AND t.party_type    = 'CUSTOMER'
AND i.PARTY_TYPE_DB = 'CUSTOMER'
)
WHEN MATCHED THEN
  UPDATE
  SET delivery_type_id = i.CF$_DELIVERY_TYPE,
      fetched          = 'TRUE'
  WHERE t.delivery_type_id IS NULL;
SELECT * FROM tax_ledger_item_tab;
IDENTITY | COMPANY | PARTY_TYPE | DELIVERY_TYPE_ID | FETCHED -------: | :------ | :--------- | ---------------: | :------ 123 | A | CUSTOMER | 456 | TRUE 查询

CREATE TABLE identity_invoice_info_cfv ( COMPANY, IDENTITY, CF$_DELIVERY_TYPE, PARTY_TYPE_DB ) AS
SELECT 'A', 123, 456, 'CUSTOMER' FROM DUAL;

CREATE TABLE tax_ledger_item_tab ( identity, company, party_type, delivery_type_id, fetched ) AS
SELECT 123, 'A', 'CUSTOMER', CAST( NULL AS NUMBER ), 'FALSE' FROM DUAL;
MERGE INTO tax_ledger_item_tab t
USING identity_invoice_info_cfv i
ON (
    t.identity      = i.identity
AND t.company       = i.COMPANY
AND t.party_type    = 'CUSTOMER'
AND i.PARTY_TYPE_DB = 'CUSTOMER'
)
WHEN MATCHED THEN
  UPDATE
  SET delivery_type_id = i.CF$_DELIVERY_TYPE,
      fetched          = 'TRUE'
  WHERE t.delivery_type_id IS NULL;
SELECT * FROM tax_ledger_item_tab;
IDENTITY | COMPANY | PARTY_TYPE | DELIVERY_TYPE_ID | FETCHED -------: | :------ | :--------- | ---------------: | :------ 123 | A | CUSTOMER | 456 | TRUE 输出

CREATE TABLE identity_invoice_info_cfv ( COMPANY, IDENTITY, CF$_DELIVERY_TYPE, PARTY_TYPE_DB ) AS
SELECT 'A', 123, 456, 'CUSTOMER' FROM DUAL;

CREATE TABLE tax_ledger_item_tab ( identity, company, party_type, delivery_type_id, fetched ) AS
SELECT 123, 'A', 'CUSTOMER', CAST( NULL AS NUMBER ), 'FALSE' FROM DUAL;
MERGE INTO tax_ledger_item_tab t
USING identity_invoice_info_cfv i
ON (
    t.identity      = i.identity
AND t.company       = i.COMPANY
AND t.party_type    = 'CUSTOMER'
AND i.PARTY_TYPE_DB = 'CUSTOMER'
)
WHEN MATCHED THEN
  UPDATE
  SET delivery_type_id = i.CF$_DELIVERY_TYPE,
      fetched          = 'TRUE'
  WHERE t.delivery_type_id IS NULL;
SELECT * FROM tax_ledger_item_tab;
IDENTITY | COMPANY | PARTY_TYPE | DELIVERY_TYPE_ID | FETCHED -------: | :------ | :--------- | ---------------: | :------ 123 | A | CUSTOMER | 456 | TRUE 身份|公司|当事人|类型|交付|类型| ID |已提取 -------: | :------ | :--------- | ---------------: | :------ 123 |客户| 456 |正确
dbfiddle

为什么使用光标?我同意Patrick的观点。使用一个UPDATE语句和一个commit可能会更快。临时表数据将由游标读取,并在整个记录中循环。是否有任何解决方法来增强此更新条件?因此,此游标需要从临时表中获取数据,并使用游标读取值更新“税务\分类账\项目\选项卡”。因为这是一个有效的问题,不值得投反对票,所以投了赞成票。分享知识。这会产生一个例外情况
ORA-38104:ON子句中引用的列无法更新:“T”。“DELIVERY\u TYPE\u ID”
T。DELIVERY\u TYPE\u ID为NULL
这需要在ON子句中删除。我已经更新了脚本。我通过这个查询获得了显著的改进,只花了102分钟就执行了这1000万条记录。