【问题标题】:what is the faster way to update a table contains around 10million records?更新包含大约 1000 万条记录的表的更快方法是什么?
【发布时间】:2018-04-03 13:09:55
【问题描述】:

我必须更新一个包含 1000 万条记录(大小为 84 GB)的表,该表从许多系统实时获取信息。

我必须将列的大小从 3 个字符扩展到 5 个字符,因为对于这个特定字段,所有新数据都将是 5 个字符。

我是否需要重新索引表以使更改更快?

我是否需要在更新活动期间停止提供此表的 cron 作业?

对上述内容的一些澄清:

我将使用此查询来更改列:

ALTER TABLE tablename MODIFY cloumnname char(5)

我们使用 Oracle 数据库。

这是我的问题:

  • 在生产中进行此更改之前,我是否需要停止所有日常 cron 作业?
  • 删除现有索引和禁用触发器会使其更快吗?

【问题讨论】:

  • 您使用的是哪个 RDBMS?如果有的话,重新索引将需要更多时间,而不是更少。
  • 如果您要更改列数据类型,这将是一个非常昂贵的查询,我想这就是您所说的更新吗?
  • SQL 服务器? mysql?后格雷斯?在您在非关键系统上运行您自己的测试之前,我不建议您做任何事情。
  • 考虑创建一个具有所需架构的新表并在创建索引之前写入该表
  • 您的问题中缺乏信息导致推测对您没有一点帮助。在您自己尝试过之后提出一个更好的问题并提供更多信息。

标签: sql oracle ddl


【解决方案1】:

TL;TR:改成varchar2(5),不要坚持char


一开始就使用char() 是个坏主意。由于char 值被填充到定义的长度,Oracle 确实需要重写表以便能够增加大小。 char 数据类型与 varchar2 类型相比没有任何优势 - 只有缺点,填充和增加其大小时的开销是其中两个。

如果您现在必须增加大小,您还应该将该列修改为 varchar,以便将来的更改不需要重写整个表。

你可以通过下面的测试脚本看到区别:

Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> desc alter_test
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER(38)
 SOME_COLUMN                                        CHAR(3)
 SOME_TS                                            TIMESTAMP(6)
 OTHER_DATA                                         NUMBER

SQL> select count(*) from alter_test;

  COUNT(*)
----------
  11520000

SQL> set timing on
SQL> alter table alter_test modify some_column char(5);

Table altered.

Elapsed: 00:01:48.19
SQL> desc alter_test2
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER(38)
 SOME_COLUMN                                        VARCHAR2(3)
 SOME_TS                                            TIMESTAMP(6)
 OTHER_DATA                                         NUMBER

SQL> select count(*) from alter_test2;

  COUNT(*)
----------
  11520000

SQL> alter table alter_test2 modify some_column varchar2(5);

Table altered.

Elapsed: 00:00:00.00
SQL>

正如您所见,增加 varchar2 的大小根本不需要时间(而不是增加 char 类型需要一分钟以上)。

因此,如果您想增加该列的允许大小而不影响您的系统,只需切换到具有新长度的合理 varchar2 类型,而忘记可怕的 char 类型。

如果你这样做,这也是一个瞬时操作:

SQL> desc alter_test
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER(38)
 SOME_COLUMN                                        CHAR(3)
 SOME_TS                                            TIMESTAMP(6)
 OTHER_DATA                                         NUMBER

SQL> select count(*) from alter_test;

  COUNT(*)
----------
  11520000

SQL> alter table alter_test modify some_column varchar2(5);

Table altered.

Elapsed: 00:00:00.02
SQL>

更新

现在从可怕的 char 更改为推荐的 varchar2 可能会对您的应用程序产生影响,如果它实际上需要空白填充值,正如 Miracle173 指出的那样。如果您的应用程序需要'Y ' 而不是'Y',那么这可能不是您可以轻松做到的(除非您还更改了应用程序)。

【讨论】:

  • 你是对的,似乎尾随空格与 CHAR 值一起存储。这与我在帖子中引用的 AskTom 文章相矛盾。使用 modify 从 CHAR(3) 更改为 VARCHAR2(5) 有一些缺点。从 CHAR(3) 更改为 VARCHAR2(5) 后,值的长度仍为 3,因此它们可能有尾随空格。所以如果你在修改命令之前插入'Y',如果你读它现在是'Y ',如果你在修改命令之后插入,它将是'Y'。所以也许整张桌子的重组会更有意义。
  • @miracle173:确实如此,但我们不知道该列中究竟存储了什么。
猜你喜欢
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 2021-11-14
  • 1970-01-01
  • 1970-01-01
  • 2017-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多