您可以使用 ALTER TABLE ... MODIFY QUERY 语句修改创建 materialized view 时指定的 SELECT 查询,而无需中断摄取过程。
此命令用于修改通过 TO [db.]name 子句创建的 materialized view。它不会更改底层存储表的结构,也不会更改 materialized view 的列定义,因此,对于未使用 TO [db.]name 子句创建的 materialized view,此命令的适用范围非常有限。
带 TO 表的示例
CREATE TABLE events (ts DateTime, event_type String)
ENGINE = MergeTree ORDER BY (event_type, ts);
CREATE TABLE events_by_day (ts DateTime, event_type String, events_cnt UInt64)
ENGINE = SummingMergeTree ORDER BY (event_type, ts);
CREATE MATERIALIZED VIEW mv TO events_by_day AS
SELECT toStartOfDay(ts) ts, event_type, count() events_cnt
FROM events
GROUP BY ts, event_type;
INSERT INTO events
SELECT DATE '2020-01-01' + interval number * 900 second,
['imp', 'click'][number%2+1]
FROM numbers(100);
SELECT ts, event_type, sum(events_cnt)
FROM events_by_day
GROUP BY ts, event_type
ORDER BY ts, event_type;
┌──────────────────ts─┬─event_type─┬─sum(events_cnt)─┐
│ 2020-01-01 00:00:00 │ click │ 48 │
│ 2020-01-01 00:00:00 │ imp │ 48 │
│ 2020-01-02 00:00:00 │ click │ 2 │
│ 2020-01-02 00:00:00 │ imp │ 2 │
└─────────────────────┴────────────┴─────────────────┘
-- 现在添加新的度量指标 `cost`
-- 以及新的维度 `browser`。
ALTER TABLE events
ADD COLUMN browser String,
ADD COLUMN cost Float64;
-- materialized view 与 TO(目标端表)中的列无需完全匹配,
-- 因此下面的 ALTER 操作不会影响数据插入。
ALTER TABLE events_by_day
ADD COLUMN cost Float64,
ADD COLUMN browser String after event_type,
MODIFY ORDER BY (event_type, ts, browser);
INSERT INTO events
SELECT Date '2020-01-02' + interval number * 900 second,
['imp', 'click'][number%2+1],
['firefox', 'safary', 'chrome'][number%3+1],
10/(number+1)%33
FROM numbers(100);
-- 新列 `browser` 和 `cost` 为空,因为我们尚未修改 Materialized View。
SELECT ts, event_type, browser, sum(events_cnt) events_cnt, round(sum(cost),2) cost
FROM events_by_day
GROUP BY ts, event_type, browser
ORDER BY ts, event_type;
┌──────────────────ts─┬─event_type─┬─browser─┬─events_cnt─┬─cost─┐
│ 2020-01-01 00:00:00 │ click │ │ 48 │ 0 │
│ 2020-01-01 00:00:00 │ imp │ │ 48 │ 0 │
│ 2020-01-02 00:00:00 │ click │ │ 50 │ 0 │
│ 2020-01-02 00:00:00 │ imp │ │ 50 │ 0 │
│ 2020-01-03 00:00:00 │ click │ │ 2 │ 0 │
│ 2020-01-03 00:00:00 │ imp │ │ 2 │ 0 │
└─────────────────────┴────────────┴─────────┴────────────┴──────┘
ALTER TABLE mv MODIFY QUERY
SELECT toStartOfDay(ts) ts, event_type, browser,
count() events_cnt,
sum(cost) cost
FROM events
GROUP BY ts, event_type, browser;
INSERT INTO events
SELECT Date '2020-01-03' + interval number * 900 second,
['imp', 'click'][number%2+1],
['firefox', 'safary', 'chrome'][number%3+1],
10/(number+1)%33
FROM numbers(100);
SELECT ts, event_type, browser, sum(events_cnt) events_cnt, round(sum(cost),2) cost
FROM events_by_day
GROUP BY ts, event_type, browser
ORDER BY ts, event_type;
┌──────────────────ts─┬─event_type─┬─browser─┬─events_cnt─┬──cost─┐
│ 2020-01-01 00:00:00 │ click │ │ 48 │ 0 │
│ 2020-01-01 00:00:00 │ imp │ │ 48 │ 0 │
│ 2020-01-02 00:00:00 │ click │ │ 50 │ 0 │
│ 2020-01-02 00:00:00 │ imp │ │ 50 │ 0 │
│ 2020-01-03 00:00:00 │ click │ firefox │ 16 │ 6.84 │
│ 2020-01-03 00:00:00 │ click │ │ 2 │ 0 │
│ 2020-01-03 00:00:00 │ click │ safary │ 16 │ 9.82 │
│ 2020-01-03 00:00:00 │ click │ chrome │ 16 │ 5.63 │
│ 2020-01-03 00:00:00 │ imp │ │ 2 │ 0 │
│ 2020-01-03 00:00:00 │ imp │ firefox │ 16 │ 15.14 │
│ 2020-01-03 00:00:00 │ imp │ safary │ 16 │ 6.14 │
│ 2020-01-03 00:00:00 │ imp │ chrome │ 16 │ 7.89 │
│ 2020-01-04 00:00:00 │ click │ safary │ 1 │ 0.1 │
│ 2020-01-04 00:00:00 │ click │ firefox │ 1 │ 0.1 │
│ 2020-01-04 00:00:00 │ imp │ firefox │ 1 │ 0.1 │
│ 2020-01-04 00:00:00 │ imp │ chrome │ 1 │ 0.1 │
└─────────────────────┴────────────┴─────────┴────────────┴───────┘
-- !!! 执行 `MODIFY ORDER BY` 时,PRIMARY KEY 被隐式引入。
SHOW CREATE TABLE events_by_day FORMAT TSVRaw
CREATE TABLE test.events_by_day
(
`ts` DateTime,
`event_type` String,
`browser` String,
`events_cnt` UInt64,
`cost` Float64
)
ENGINE = SummingMergeTree
PRIMARY KEY (event_type, ts)
ORDER BY (event_type, ts, browser)
-- !!! 列的定义未发生变化,但这无关紧要——我们查询的不是
-- MATERIALIZED VIEW,而是 TO(存储)表。
-- SELECT 部分已更新。
SHOW CREATE TABLE mv FORMAT TSVRaw;
CREATE MATERIALIZED VIEW test.mv TO test.events_by_day
(
`ts` DateTime,
`event_type` String,
`events_cnt` UInt64
) AS
SELECT
toStartOfDay(ts) AS ts,
event_type,
browser,
count() AS events_cnt,
sum(cost) AS cost
FROM test.events
GROUP BY
ts,
event_type,
browser不带 TO 表的示例
该应用场景限制较多,因为你只能修改 SELECT 部分,无法添加新列。
CREATE TABLE src_table (`a` UInt32) ENGINE = MergeTree ORDER BY a;
CREATE MATERIALIZED VIEW mv (`a` UInt32) ENGINE = MergeTree ORDER BY a AS SELECT a FROM src_table;
INSERT INTO src_table (a) VALUES (1), (2);
SELECT * FROM mv;┌─a─┐
│ 1 │
│ 2 │
└───┘ALTER TABLE mv MODIFY QUERY SELECT a * 2 as a FROM src_table;
INSERT INTO src_table (a) VALUES (3), (4);
SELECT * FROM mv;┌─a─┐
│ 6 │
│ 8 │
└───┘
┌─a─┐
│ 1 │
│ 2 │
└───┘ALTER TABLE … MODIFY REFRESH 语句
ALTER TABLE ... MODIFY REFRESH 用于更改可刷新materialized view 的刷新参数,包括调度、依赖关系、随机化以及刷新设置。
ALTER TABLE [db.]name MODIFY REFRESH EVERY|AFTER ... [RANDOMIZE FOR ...] [DEPENDS ON ...] [SETTINGS ...]调度 (EVERY 或 AFTER) 是必需的:该语句会一次性替换所有刷新参数。任何未指定的子句——RANDOMIZE FOR、DEPENDS ON 或 SETTINGS——都会被移除或重置为默认值。若只想更改刷新设置,请重复当前调度。
该命令会就地更新现有视图的刷新配置,无需重新创建 materialized view 或其目标表,也不会清除现有目标数据或取消正在进行的刷新。更改配置期间,读取操作会继续针对现有目标表进行。
使用相同的完整 REFRESH 规范重复执行该命令是安全的。请务必重复应保留配置的每个子句,因为如上所述,每次执行都会替换所有刷新参数。
-- Change the schedule.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE;
-- Change retry settings (schedule must be repeated).
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE
SETTINGS refresh_retries = 5,
refresh_retry_initial_backoff_ms = 500,
refresh_retry_max_backoff_ms = 60000;
-- Add or keep a dependency.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR DEPENDS ON other_rmv;
-- Drop the dependency by omitting `DEPENDS ON`.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR;限制:
- 不支持对 materialized view 执行
ALTER TABLE ... MODIFY SETTING;刷新设置只能通过MODIFY REFRESH修改。 - 不支持添加或移除
APPEND。 - 视图创建后,无法更改
all_replicas刷新设置。
完整的刷新设置列表见刷新设置。刷新状态 (包括当前生效的设置) 可在 system.view_refreshes 中查看。