更改列宽

可以扩展同一类数据类型中的列。这样做对于在列中存储较大的项目很有用。Vertica 在执行转换之前会验证数据。

通常,还可以减小数据类型类中的列宽。如果原始声明的长度比您需要的要长,这对于回收存储很有用,特别是对于字符串。仅当满足以下条件时,才能减小列宽:

  • 现有列数据不大于新宽度。

  • 数据库群集中的所有节点都已启动。

否则,Vertica 会返回错误并且转换失败。例如,如果尝试将列从 varchar(25) 转换为 varchar(10),只要所有列数据不超过 10 个字符,Vertica 就允许转换。

在以下示例中,列 yz 最初定义为 VARCHAR 数据类型,并分别加载值 12345654321。将列 z 的宽度减小到 5 的尝试失败,因为它包含六个字符的数据。将列 y 的宽度减小到 5 的尝试成功,因为它的内容符合新的宽度:

=> CREATE TABLE t (x int, y VARCHAR, z VARCHAR);
CREATE TABLE
=> CREATE PROJECTION t_p1 AS SELECT * FROM t SEGMENTED BY hash(x) ALL NODES;
CREATE PROJECTION
=> INSERT INTO t values(1,'12345','654321');
 OUTPUT
--------
      1
(1 row)

=> SELECT * FROM t;
 x |   y   |   z
---+-------+--------
 1 | 12345 | 654321
(1 row)

=> ALTER TABLE t ALTER COLUMN z SET DATA TYPE char(5);
ROLLBACK 2378:  Cannot convert column "z" to type "char(5)"
HINT:  Verify that the data in the column conforms to the new type
=> ALTER TABLE t ALTER COLUMN y SET DATA TYPE char(5);
ALTER TABLE

更改集合列

如果列是集合数据类型,则可以使用 ALTER TABLE 更改其边界或最大二进制大小。这些属性是在表创建时设置的,随后可以更改。

您可以使集合有界,设置其最大元素数,如下面的示例所示。

=> ALTER TABLE test.t1 ALTER COLUMN arr SET DATA TYPE array[int,10];
ALTER TABLE

=> \d test.t1
                                     List of Fields by Tables
 Schema | Table | Column |      Type       | Size | Default | Not Null | Primary Key | Foreign Key
--------+-------+--------+-----------------+------+---------+----------+-------------+-------------
  test  |  t1   | arr    | array[int8, 10] |   80 |         | f        | f           |
(1 row)

或者,可以设置整个集合的二进制大小,而不是设置边界。二进制大小是显式设置的,也可以通过 DefaultArrayBinarySize 配置参数设置。下面的示例从默认值创建一个数组列,更改默认值,然后使用 ALTER TABLE 将其更改为新的默认值。

=> SELECT get_config_parameter('DefaultArrayBinarySize');
 get_config_parameter
----------------------
 100
(1 row)

=> CREATE TABLE test.t1 (arr array[int]);
CREATE TABLE

=> \d test.t1
                                     List of Fields by Tables
 Schema | Table | Column |      Type       | Size | Default | Not Null | Primary Key | Foreign Key
--------+-------+--------+-----------------+------+---------+----------+-------------+-------------
  test  |  t1   | arr    | array[int8](96) |   96 |         | f        | f           |
(1 row)

=> ALTER DATABASE DEFAULT SET DefaultArrayBinarySize=200;
ALTER DATABASE

=> ALTER TABLE test.t1 ALTER COLUMN arr SET DATA TYPE array[int];
ALTER TABLE

=> \d test.t1
                                     List of Fields by Tables
 Schema | Table | Column |      Type       | Size | Default | Not Null | Primary Key | Foreign Key
--------+-------+--------+-----------------+------+---------+----------+-------------+-------------
  test  |  t1   | arr    | array[int8](200)|  200 |         | f        | f           |
(1 row)

或者,可以显式设置二进制大小,而不是使用默认值。

=> ALTER TABLE test.t1 ALTER COLUMN arr SET DATA TYPE array[int](300);

清除历史数据

如果 Vertica 保留任何超过新宽度的历史数据,则无法减小列的宽度。要减小列宽,首先从表中移除该数据:

  1. 将 AHM 推进到比需要从表中移除的历史数据更近的时期。

  2. 使用函数 PURGE_TABLE 清除表中 AHM 之前的所有历史数据。

例如,在前面的示例中,您可以更新 t.z 列中的数据,如下所示:

=> UPDATE t SET z = '54321';
 OUTPUT
--------
      1
(1 row)

=> SELECT * FROM t;
 x |   y   |   z
---+-------+-------
 1 | 12345 | 54321
(1 row)

尽管现在 z 列中没有数据超过 5 个字符,但 Vertica 保留了其早期数据的历史记录,因此尝试将列宽减小到 5 会返回错误:

=> ALTER TABLE t ALTER COLUMN z SET DATA TYPE char(5);
ROLLBACK 2378:  Cannot convert column "z" to type "char(5)"
HINT:  Verify that the data in the column conforms to the new type

您可以通过清除表的历史数据来减小列宽,如下所示:

=> SELECT MAKE_AHM_NOW();
         MAKE_AHM_NOW
-------------------------------
 AHM set (New AHM Epoch: 6350)
(1 row)

=> SELECT PURGE_TABLE('t');
                                                     PURGE_TABLE
----------------------------------------------------------------------------------------------------------------------
 Task: purge operation
(Table: public.t) (Projection: public.t_p1_b0)
(Table: public.t) (Projection: public.t_p1_b1)

(1 row)

=> ALTER TABLE t ALTER COLUMN z SET DATA TYPE char(5);
ALTER TABLE