ClickHouse/docs/zh/operations/table_engines/merge.md
2020-01-30 13:34:55 +03:00

70 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Merge
`Merge` 引擎 (不要跟 `MergeTree` 引擎混淆) 本身不存储数据,但可用于同时从任意多个其他的表中读取数据。
读是自动并行的,不支持写入。读取时,那些被真正读取到数据的表的索引(如果有的话)会被使用。
`Merge` 引擎的参数:一个数据库名和一个用于匹配表名的正则表达式。
示例:
```
Merge(hits, '^WatchLog')
```
数据会从 `hits` 数据库中表名匹配正则 '`^WatchLog`' 的表中读取。
除了数据库名,你也可以用一个返回字符串的常量表达式。例如, `currentDatabase()`
正则表达式 — [re2](https://github.com/google/re2) (支持 PCRE 一个子集的功能),大小写敏感。
了解关于正则表达式中转义字符的说明可参看 "match" 一节。
当选择需要读的表时,`Merge` 表本身会被排除,即使它匹配上了该正则。这样设计为了避免循环。
当然,是能够创建两个相互无限递归读取对方数据的 `Merge` 表的,但这并没有什么意义。
`Merge` 引擎的一个典型应用是可以像使用一张表一样使用大量的 `TinyLog` 表。
示例 2
我们假定你有一个旧表WatchLog_old你想改变数据分区了但又不想把旧数据转移到新表WatchLog_new并且你需要同时能看到这两个表的数据。
```
CREATE TABLE WatchLog_old(date Date, UserId Int64, EventType String, Cnt UInt64)
ENGINE=MergeTree(date, (UserId, EventType), 8192);
INSERT INTO WatchLog_old VALUES ('2018-01-01', 1, 'hit', 3);
CREATE TABLE WatchLog_new(date Date, UserId Int64, EventType String, Cnt UInt64)
ENGINE=MergeTree PARTITION BY date ORDER BY (UserId, EventType) SETTINGS index_granularity=8192;
INSERT INTO WatchLog_new VALUES ('2018-01-02', 2, 'hit', 3);
CREATE TABLE WatchLog as WatchLog_old ENGINE=Merge(currentDatabase(), '^WatchLog');
SELECT *
FROM WatchLog
┌───────date─┬─UserId─┬─EventType─┬─Cnt─┐
│ 2018-01-01 │ 1 │ hit │ 3 │
└────────────┴────────┴───────────┴─────┘
┌───────date─┬─UserId─┬─EventType─┬─Cnt─┐
│ 2018-01-02 │ 2 │ hit │ 3 │
└────────────┴────────┴───────────┴─────┘
```
## 虚拟列
虚拟列是一种由表引擎提供而不是在表定义中的列。换种说法就是,这些列并没有在 `CREATE TABLE` 中指定,但可以在 `SELECT` 中使用。
下面列出虚拟列跟普通列的不同点:
- 虚拟列不在表结构定义里指定。
- 不能用 `INSERT` 向虚拟列写数据。
- 使用不指定列名的 `INSERT` 语句时,虚拟列要会被忽略掉。
- 使用星号通配符( `SELECT *` )时虚拟列不会包含在里面。
- 虚拟列不会出现在 `SHOW CREATE TABLE``DESC TABLE` 的查询结果里。
`Merge` 类型的表包括一个 `String` 类型的 `_table` 虚拟列。(如果该表本来已有了一个 `_table` 的列,那这个虚拟列会命名为 `_table1` ;如果 `_table1` 也本就存在了,那这个虚拟列会被命名为 `_table2` ,依此类推)该列包含被读数据的表名。
如果 `WHERE/PREWHERE` 子句包含了带 `_table` 的条件,并且没有依赖其他的列(如作为表达式谓词链接的一个子项或作为整个的表达式),这些条件的作用会像索引一样。这些条件会在那些可能被读数据的表的表名上执行,并且读操作只会在那些满足了该条件的表上去执行。
[来源文章](https://clickhouse.tech/docs/en/operations/table_engines/merge/) <!--hide-->