【问题标题】:Insert sequence taking long time插入序列需要很长时间
【发布时间】:2017-12-05 04:32:22
【问题描述】:

我在 Oracle 中有一张表:

table1

record_id    variable     value
1            100          50
1            101          40
2            100          30
2            101          60
1            102          100

它有超过 700 万行。我想添加另一列作为唯一 ID。所以,表格看起来像:

table1

id          record_id    variable     value
1           1            100          50
2           1            101          40
3           2            100          30
4           2            101          60
5           1            102          100

但是当我尝试使用以下方法更新它时:

更新表1 SET id = my_sequence.nextval;

这需要很长时间。有没有更快的方法来完成这项工作?

这里是创建表查询:

CREATE TABLE "ABCUSER"."NUM_VAL"
("RECORD_ID" NUMBER(*,0),
"VAR" NUMBER,
"VAR_SEQUENCE" NUMBER,
"VAR_DATATYPE" NUMBER,
"CREATED_DATE" DATE,
"UPDATED_DATE" DATE,
"VAR_VALUE_NUMBER" VARCHAR2(40 BYTE),
"VAR_VALUE_TEXT" VARCHAR2(255 BYTE),
"VAR_VALUE_DATE" DATE,
"ID" NUMBER
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS NOLOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS" ;

CREATE INDEX "ABCUSER"."IMD_TB_UNIQUE_ID" ON "ABCUSER"."NUM_VAL" ("RECORD_ID")
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS" ;

顺序:

CREATE SEQUENCE "ABCUSER"."MY_SEQUENCE" MINVALUE 1 MAXVALUE 9999999999999999999999999999 增量 1 START WITH 10186338807 缓存 100 NOORDER NOCYCLE ;

【问题讨论】:

  • @MikeNakis - 完成
  • pOrinG 的答案会起作用,但我认为它不会产生任何巨大的性能优势,因为序列是高度优化的。如果序列是瓶颈,则很容易将序列的CACHE 子句从100 更改为100010000,以将其性能提高几个数量级。我认为您还应该定义“很长时间”的含义,因为即使在最佳情况下,700 万条记录也需要一些时间来更新。
  • Oracle 的哪个版本?

标签: sql oracle performance


【解决方案1】:

更新所有 700 万行(整个表)必须花费一些时间。
更快的方法是创建此表的副本:

CREATE TABLE NUM_VAL_copy AS SELECT 
   "RECORD_ID"  ,
   "VAR" ,
   "VAR_SEQUENCE" ,
   "VAR_DATATYPE"  ,
   "CREATED_DATE" ,
   "UPDATED_DATE" ,
   "VAR_VALUE_NUMBER",
   "VAR_VALUE_TEXT" ,
   "VAR_VALUE_DATE" ,
   my_sequence.nextval AS "ID"
FROM NUM_VAL;

然后索引 new_table、授予权限、在新表上添加约束等。
最后删除旧表并将新表重命名为旧名称:

DROP TABLE NUM_VAL;
RENAME NUM_VAL_COPY TO NUM_VAL;

详情请查看文档:https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9019.htm#SQLRF01608

【讨论】:

    【解决方案2】:

    如果您希望序列以 1...2...3... 开头,那么您可以使用以下命令。

    update table_name set unique_seq = rownum;
    

    我在一张有 6 条记录的表上试了一下,效果很好。我不能 100% 确定这是否是理想的方式,但我认为它会比 nextval 更快。

    稍后如果您出于某种原因仍然想要您定义的序列,您可以更新 oracle 序列以从 max(unique_seq) 数字开始。

    【讨论】:

      【解决方案3】:
      1. 如果您使用的是 Oracle RAC,这可能是个问题。一个小的缓存序列会对性能产生影响。不使用顺序,缓存来创建您的序列。

      2. 700 万行并不是一个大数字。您可能需要检查更新期间是否存在应用程序阻止问题。那是 DBA 的工作。他们将需要为您检查锁。

      3. 如果您可以创建表作为选择来添加值,它将比更新快得多。

      将 table1 重命名为 table2 ; create table table1 select /*+ append */ *, [idvalue] id from table2 ;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-24
        • 2016-08-13
        • 2014-02-22
        • 2012-07-17
        • 1970-01-01
        • 2017-10-06
        • 2019-11-20
        • 2011-06-06
        相关资源
        最近更新 更多