# ALTER

> ALTER 用于修改数据库的设置、表的设置或表的元数据。

# ALTER

`ALTER` 可以用来修改数据库的设置，表的设置或表的元数据，包括：

* 修改数据库选项
* 添加/删除/修改列
* 设置/取消列默认值
* 重命名表
* 修改表选项

## ALTER DATABASE

`ALTER DATABASE` 语句可以用来修改数据库的选项。

### 语法

```sql
ALTER DATABASE db
   [SET <option_name>=<option_value> [, ...]
    | UNSET <option_name> [, ...]
   ]
```

当前支持修改以下数据库选项：
- `ttl`: 数据库中数据的默认保留时间。过期的数据会被异步删除。
   - 如果之前未设置 ttl，通过 `ALTER` 设置新的 ttl 后，超过保留时间的数据将被删除。
   - 如果之前已设置过 ttl，通过 `ALTER` 修改 ttl 后，新的保留时间将立即生效，超过新保留时间的数据将被删除。
   - 如果之前已设置过 ttl，通过 `ALTER` 取消 ttl 设置后，新增的数据将不会被删除，但已被删除的数据无法恢复。
- `compaction.twcs.time_window`: TWCS 压缩策略的时间窗口参数。值应该是一个[时间长度字符串](/reference/time-durations.md)。对此选项的修改会立即影响所有没有明确设置压缩选项的表。
- `compaction.twcs.max_output_file_size`: TWCS 压缩策略的最大允许输出文件大小。对此选项的修改会立即影响所有没有明确设置压缩选项的表。
- `compaction.twcs.trigger_file_num`: 触发压缩的特定时间窗口中的文件数。对此选项的修改会立即影响所有没有明确设置压缩选项的表。

### 示例

#### 修改数据库中数据的默认保留时间

修改数据库中数据的默认保留时间为 1 天：

```sql
ALTER DATABASE db SET 'ttl'='1d';
```

取消数据库中数据的默认保留时间设置：

```sql
ALTER DATABASE db UNSET 'ttl';
```

#### 修改数据库的压缩选项

数据库级别的压缩选项在压缩调度时动态解析。当您修改这些选项时，更改会立即影响数据库中所有没有明确设置压缩选项的表，类似于 TTL 的工作方式。

修改数据库的压缩时间窗口：

```sql
ALTER DATABASE db SET 'compaction.twcs.time_window'='2h';
```

修改压缩的最大输出文件大小：

```sql
ALTER DATABASE db SET 'compaction.twcs.max_output_file_size'='500MB';
```

修改触发压缩的文件数：

```sql
ALTER DATABASE db SET 'compaction.twcs.trigger_file_num'='8';
```

取消压缩选项：

```sql
ALTER DATABASE db UNSET 'compaction.twcs.time_window';
```

## ALTER TABLE

## 语法

```sql
ALTER TABLE [db.]table
   [ADD COLUMN name1 type1 [options], ADD COLUMN name2 type2 [options], ...
    | DROP COLUMN name
    | MODIFY COLUMN name type
    | MODIFY COLUMN name SET DEFAULT value
    | MODIFY COLUMN name DROP DEFAULT
    | MODIFY COLUMN name SET FULLTEXT INDEX [WITH <options>]
    | MODIFY COLUMN name UNSET FULLTEXT INDEX
    | PARTITION ON COLUMNS (<column_list>) (<expr_list>)
    | SPLIT PARTITION (<expr>) [ON COLUMNS (<column_list>)] INTO (<expr_list>)
    | MERGE PARTITION (<expr_list>)
    | RENAME name
    | SET <option_name>=<option_value> [, ...]
    | UNSET <option_name> [, ...]
    ]
```

### 增加列

在表中增加新列：

```sql
ALTER TABLE monitor ADD COLUMN load_15 double;
```

列的定义和 [CREATE](./create.md) 中的定义方式一样。

我们可以在表中同时增加多个列：

```sql
ALTER TABLE monitor ADD COLUMN disk_usage double, ADD COLUMN disk_free double;
```

我们可以设置新列的位置。比如放在第一位：

```sql
ALTER TABLE monitor ADD COLUMN load_15 double FIRST;
```

或者放在某个已有列之后：

```sql
ALTER TABLE monitor ADD COLUMN load_15 double AFTER memory;
```

增加一个带默认值的 Tag 列（加入 Primary key 约束）：
```sql
ALTER TABLE monitor ADD COLUMN app STRING DEFAULT 'shop' PRIMARY KEY;
```

### 移除列

从表中移除列：

```sql
ALTER TABLE monitor DROP COLUMN load_15;
```

后续的所有查询立刻不能获取到被移除的列。

### 修改列类型

修改列的数据类型

```sql
ALTER TABLE monitor MODIFY COLUMN load_15 STRING;
```

被修改的列不能是 tag 列（primary key）或 time index 列，同时该列必须允许空值 `NULL` 存在来保证数据能够安全地进行转换（转换失败时返回 `NULL`）。

### 设置列默认值

为现有列设置默认值：

```sql
ALTER TABLE monitor MODIFY COLUMN load_15 SET DEFAULT 0.0;
```

设置字符串默认值：

```sql
ALTER TABLE monitor MODIFY COLUMN `status` SET DEFAULT 'active';
```

默认值将在插入新行时使用，当该列没有显式提供值时。

移除列的默认值：

```sql
ALTER TABLE monitor MODIFY COLUMN load_15 DROP DEFAULT;
```

删除默认值后，该列将使用 `NULL` 作为默认值。数据库只允许对可为空的列删除默认值。

<AnchorAlias id="alter-table-options" />

### 修改表的参数

`ALTER TABLE` 语句也可以用来更改表的选项。
当前支持修改以下表选项：
- `ttl`: 表数据的保留时间。
- `append_mode`: 表是否为 append-only。你可以将其从 `false` 更改为 `true`，但之后不能再改回 `false`。
- `compaction.twcs.time_window`: TWCS compaction 策略的时间窗口，其值是一个[时间范围字符段](/reference/time-durations.md)。
- `compaction.twcs.max_output_file_size`: TWCS compaction 策略的最大允许输出文件大小。
- `compaction.twcs.trigger_file_num`: 某个窗口内触发 compaction 的最小文件数量阈值。
- `sst_format`: 表的 SST 格式。值可以是 `flat` 或 `primary_key`。表支持双向格式转换：`primary_key` 转换为 `flat`，以及 `flat` 转换为 `primary_key`。
- `write_buffer_size`: 表的单 region 写缓冲区阻塞阈值。设置为 `512MB` 等正值后，mutable memtable 内存用量达到该值的一半时，GreptimeDB 会调度 flush；达到该值时会阻塞写入，达到该值的 2 倍时会拒绝写入。该表选项会覆盖 `region_engine.mito.default_region_write_buffer_size`。即使引擎默认值非零，显式设置为 `0` 也会禁用单 region 限制。取消设置会移除表级覆盖，并回退到引擎默认值。
- `auto_flush_interval`: 该表的 region 最长多久没有 flush 就触发一次 flush。值是一个[时间范围字符串](/reference/time-durations.md)，必须大于 0。该表选项会覆盖引擎级的 `region_engine.mito.auto_flush_interval`。
- `skip_wal`: 是否为该表禁用预写日志（WAL）。当设置为 `'true'` 时表的写入数据将不会持久化到预写日志，可以提升写入吞吐。但是当进程重启时，尚未 flush 的数据会丢失。请仅在数据源本身可以确保可靠性的情况下使用此功能。你可以将其从 `false` 更改为 `true`，但之后不能再改回 `false`，也不支持 `UNSET`。仅支持在使用 `mito` 或 `metric` 引擎的物理表上启用，且必须单独设置，不能在同一条 `ALTER TABLE` 中与其他 table option 一起修改。
- `max_row_group_row_count`: Parquet row group 的最大行数。取值必须在 `1` 到 `10485760`（`10 * 1024 * 1024`）之间，设置为零会被拒绝。修改或取消该选项时，GreptimeDB 会先使用旧的 row group 大小 flush 尚未落盘的数据，再应用新值。新值，或取消设置后的默认值 `102400`（`100 * 1024`），会应用于后续生成的 SST。ALTER 操作不会立即重写已有 SST；后续 compaction 可能会使用当前的 row group 大小重写这些 SST。

```sql
ALTER TABLE monitor SET 'ttl'='1d';

ALTER TABLE monitor SET 'append_mode'='true';

ALTER TABLE monitor SET 'compaction.twcs.time_window'='2h';

ALTER TABLE monitor SET 'compaction.twcs.max_output_file_size'='500MB';

ALTER TABLE monitor SET 'compaction.twcs.trigger_file_num'='8';

ALTER TABLE monitor SET 'sst_format'='flat';

ALTER TABLE monitor SET 'sst_format'='primary_key';

ALTER TABLE monitor SET 'write_buffer_size'='512MB';

ALTER TABLE monitor SET 'auto_flush_interval'='5m';

ALTER TABLE monitor SET 'skip_wal'='true';

ALTER TABLE monitor SET 'max_row_group_row_count'='2048';
```

要移除 `auto_flush_interval` 的表级覆盖、回退到引擎级配置，把它设为 `NULL`：

```sql
ALTER TABLE monitor SET 'auto_flush_interval' = NULL;
```

:::warning
`auto_flush_interval` 不支持 `UNSET`。执行 `ALTER TABLE monitor UNSET 'auto_flush_interval'`
会报错，请用上面的 `SET ... = NULL`。
:::

### 移除表参数

```sql
ALTER TABLE monitor UNSET 'ttl';

ALTER TABLE monitor UNSET 'write_buffer_size';

ALTER TABLE monitor UNSET 'max_row_group_row_count';
```

### 设置重分区列 hint

:::info 企业版功能
该选项仅在 GreptimeDB Enterprise 中可用。详细说明请参考 [Auto Repartition](/enterprise/autopilot/auto-repartition.md)。
:::

在 GreptimeDB Enterprise 中，可以在 `CREATE TABLE ... WITH` 中指定 `repartition.column.hint`，也可以后续通过 `ALTER TABLE` 修改。

对于未分区表，可以设置 Auto Repartition 使用的候选列：

```sql
ALTER TABLE table_name SET 'repartition.column.hint'='column_name';
```

取消该 hint：

```sql
ALTER TABLE table_name UNSET 'repartition.column.hint';
```

该 hint 只会记录供后续 Auto Repartition 使用的元信息，不会立即触发重分区。

使用 `ALTER TABLE` 时，该 hint 必须单独设置或取消，不能和其他 table options 一起修改。

<AnchorAlias id="split-or-merge-partitions" />

### 重分区、拆分与合并

使用 `PARTITION ON COLUMNS` 可以将未分区的表重分区为多个分区：

```sql
ALTER TABLE sensor_readings PARTITION ON COLUMNS (device_id, area) (
  device_id < 100 AND area < 'South',
  device_id < 100 AND area >= 'South',
  device_id >= 100 AND area <= 'East',
  device_id >= 100 AND area > 'East'
);
```

使用 `SPLIT PARTITION` 将一个已有分区拆分为多个分区：

```sql
ALTER TABLE sensor_readings SPLIT PARTITION (
  device_id < 100
) INTO (
  device_id < 100 AND area < 'North',
  device_id < 100 AND area >= 'North'
);
```

若还需要在拆分时引入新的分区列，可以添加 `ON COLUMNS`。以下示例假设表当前仅按 `device_id` 分区，`ON COLUMNS (device_id, area)` 会将 `area` 引入为新的分区列：

```sql
ALTER TABLE sensor_readings SPLIT PARTITION (
  device_id < 100
) ON COLUMNS (device_id, area) INTO (
  device_id < 100 AND area < 'South',
  device_id < 100 AND area >= 'South'
);
```

如果省略 `ON COLUMNS`，则保留现有的分区列。

使用 `MERGE PARTITION` 将多个分区合并为一个分区。以下示例将两个分区合并为一个覆盖 `device_id < 100` 的分区：

```sql
ALTER TABLE sensor_readings MERGE PARTITION (
  device_id < 100 AND area < 'South',
  device_id < 100 AND area >= 'South'
);
```

你可以在任意重分区语句末尾附加 DDL 选项以控制执行行为：

```sql
ALTER TABLE sensor_readings SPLIT PARTITION (
  device_id < 100
) INTO (
  device_id < 100 AND area < 'South',
  device_id < 100 AND area >= 'South'
) WITH (
  TIMEOUT = '5m',
  WAIT = false
);
```

当 `WAIT = false` 时，语句会返回 `procedure_id`，可通过 `ADMIN procedure_state(procedure_id)` 查询状态（参见 [ADMIN](/reference/sql/admin.md)）。
`TIMEOUT` 用于控制整个操作的超时时间，无论 `WAIT` 是否为 `true` 都会生效。

:::caution 注意
重分区相关操作仅支持在分布式集群中执行。
必须开启共享对象存储和 GC，并确保所有 datanode 都能访问同一对象存储后再执行这些语句。
:::

<AnchorAlias id="create-an-index-for-a-column" />

### 创建列的索引

在列上启用倒排索引：

```sql
ALTER TABLE monitor MODIFY COLUMN host SET INVERTED INDEX;
```

启用列的全文索引：

```sql
ALTER TABLE monitor MODIFY COLUMN load_15 SET FULLTEXT INDEX WITH (analyzer = 'English', case_sensitive = 'false', backend = 'bloom');
```

在启用列的全文索引时，可以使用 `FULLTEXT INDEX WITH` 指定以下选项：

- `analyzer`：设置全文索引的分析器语言。支持的值为 `English` 和 `Chinese`。默认为 `English`。
- `case_sensitive`：设置全文索引是否区分大小写。支持的值为 `true` 和 `false`。默认为 `false`。
- `backend`：设置全文索引的后端实现。支持的值为 `bloom` 和 `tantivy`。默认为 `bloom`。
- `granularity`：（适用于 `bloom` 后端）每个过滤器覆盖的数据块大小。粒度越小，过滤效果越好，但索引大小会增加。默认为 `10240`。
- `false_positive_rate`：（适用于 `bloom` 后端）错误识别块的概率。该值越低，准确性越高（过滤效果越好），但索引大小会增加。该值为介于 `0` 和 `1` 之间的浮点数。默认为 `0.01`。

更多关于全文索引配置和性能对比的信息，请参考[全文索引配置指南](/user-guide/manage-data/data-index.md#全文索引)。

与 `CREATE TABLE` 一样，可以不带 `WITH` 选项，全部使用默认值。

启用列上的跳数索引：
```sql
ALTER TABLE monitor MODIFY COLUMN host SET SKIPPING INDEX WITH(granularity = 1024, type = 'BLOOM');
```

跳数索引的有效选项包括：
* `type`: 索引类型，目前仅支持 `BLOOM` 即布隆过滤器。
* `granularity`: （适用于 `BLOOM` 类型）每个过滤器覆盖的数据块大小。粒度越小，过滤效果越好，但索引大小会增加。默认为 `10240`。
* `false_positive_rate`: （适用于 `BLOOM` 类型）错误识别块的概率。该值越低，准确性越高（过滤效果越好），但索引大小会增加。该值为介于 `0` 和 `1` 之间的浮点数。默认为 `0.01`。

### 移除列的索引

语法如下：

```sql
ALTER TABLE [table] MODIFY COLUMN [column] UNSET [INVERTED | SKIPPING | FULLTEXT] INDEX;
```

例如，移除倒排索引：

```sql
ALTER TABLE monitor_pk MODIFY COLUMN host UNSET INVERTED INDEX;
```

移除跳数索引：

```sql
ALTER TABLE monitor_pk MODIFY COLUMN host UNSET SKIPPING INDEX;
```

移除全文索引：

```sql
ALTER TABLE monitor MODIFY COLUMN load_15 UNSET FULLTEXT INDEX;
```

修改列的全文索引选项时，列的数据类型必须是字符串类型。

当列的全文索引未开启过时，可以启用全文索引，并设置 `analyzer` 和 `case_sensitive` 选项；当列的全文索引选项已经启用时，可以关闭全文索引，**但不能修改选项，跳数索引也是如此**。

### 重命名表

```sql
ALTER TABLE monitor RENAME monitor_new;
```

该命令只是重命名表，不会修改表中的数据。
