1000万条记录sql更新耗时4天

Posted

技术标签:

【中文标题】1000万条记录sql更新耗时4天【英文标题】:Sql update takes 4 days for 10 million records 【发布时间】:2019-03-28 06:55:23 【问题描述】:

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

1.) 我已经为更新搜索条件创建了一个索引 tax_ledger_item_tab。在party_type、身份、公司上创建的索引。 我的搜索条件是party_type、identity、company、delivery_type_id 如以下给定查询,这些列不是表中的键。

我相信我不能为索引添加delivery_type_id,因为它会 通过查询更新,如果我将其添加到索引中,性能将是最差的。

2.) 临时表 identity_invoice_info_cfv 也将返回 70,000 条记录 也。

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

如何通过以下更新查询来提高性能?我只想更新delivery_type_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;

【问题讨论】:

为什么要使用光标?? 我同意帕特里克的观点。使用带有单个提交的单个 UPDATE 语句可能会更快 游标会读取临时表数据并循环遍历整个记录。是否有任何解决方法来增强此更新标准? 所以这个游标需要从临时表中获取数据并使用游标读取值更新 tax_ledger_item_tab。 赞成只是因为这是一个有效的问题,不值得反对。分享知识。 【参考方案1】:

使用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;

输出

身份 |公司 |派对类型 | DELIVERY_TYPE_ID |已取回 --------: | :-------- | :--------- | ---------------: | :------ 123 |一个 |客户 |第456章真的

db小提琴here

【讨论】:

我用这个查询得到了显着的改进,只用了 102 分钟来执行这 1000 万条记录。【参考方案2】:

我希望你也可以使用 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;

【讨论】:

这给出了一个例外ORA-38104: Columns referenced in the ON Clause cannot be updated: "T"."DELIVERY_TYPE_ID" t.delivery_type_id IS NULL 这需要在 on 子句中删除。我已经更新了脚本

以上是关于1000万条记录sql更新耗时4天的主要内容,如果未能解决你的问题,请参考以下文章

数据库快速插入1000万条记录

数据库快速插入1000万条记录

Mysql慢查询开启和查看 ,存储过程批量插入1000万条记录进行慢查询测试

如何在 SQL Server 中更新具有数百万行的大表?

批量向MySQL导入1000万条数据的优化

第8天SQL进阶-更新记录(SQL 小虚竹)