比较ClickHouse三种表字段默认值表达式

本文介绍了ClickHouse中定义表字段默认值的三种方式——DEFAULT、MATERIALIZED和ALIAS。MATERIALIZED和ALIAS在数据写入和查询时有特定行为:MATERIALIZED列数据会被持久化,适合复杂计算;ALIAS列不持久化,仅在查询时计算。文章通过示例展示了这两种表达式的使用,并建议在需要提高查询性能时使用物化列。

ClickHouse表字段支持三种默认值表达式的定义方法,分别是DEFAULT、MATERIALIZED和ALIAS。Default其他RDBMS也支持,比较常用,本文注意介绍后两者表达式的差异,并通过示例分别进行介绍。

数据类型

无论使用哪种形式,表字段一旦被定义了默认值,它便不再强制要求定义数据类型,因为ClickHouse会根据默认值进行类型推断。如果同时对表字段定义了数据类型和默认值表达式,则以明确定义的数据类型为主,例如下面的例子:

CREATE TABLE dfv_v1 (
    id String,
    c1 DEFAULT 1000,
    c2 String DEFAULT c1
) ENGINE = TinyLog

c1字段没有定义数据类型,默认值为整型1000;c2字段定义了数据类型和默认值,且默认值等于c1。根据默认值的优先级顺序,其中c1字段根据默认值被推断为UInt16;而c2字段由于同时定义了数据类型和默认值,所以它最终的数据类型来自明确定义的String。

alias表达式

alias列没有序列化,是在查询时才计算。因此不适合复杂计算,示例如下:

CREATE TABLE test_new_col
 (
    `_csv` String,
    `csv_as_array` Array(String) ALIAS splitByChar(';',_csv),
    `csv_col1` String DEFAULT csv_as_array[1],
    `csv_col2` String DEFAULT csv_as_array[2]
)
ENGINE = MergeTree
ORDER BY tuple();

INSERT INTO test_new_col (_csv) values
    ('a1;b1;c1;d1'), 
    ('a2;b2;c2;d2'), 
    ('a3;b3;c3;d3');

SELECT csv_col1, csv_col2 FROM test_new_col;

查询结果:

Query id: 45e5ded7-3b93-4bc0-b825-47c4310d21cf

┌─csv_col1─┬─csv_col2─┐
│ a1       │ b1       │
│ a2       │ b2       │
│ a3       │ b3       │
└──────────┴──────────┘

我们再增加一列:

ALTER TABLE test_new_col ADD COLUMN `csv_col3` String DEFAULT csv_as_array[3];

SELECT csv_col3 FROM test_new_col

┌─csv_col3─┐
│ c1       │
│ c2       │
│ c3       │
└──────────┘

物化列

使用默认值(default或MATERIALIZED)的表达式会持久化列数据。如果需要使用复杂的表达式查询数据,会避免在SELECT执行时直接计算这样的表达式会非常昂贵。

举例,下面查询需要使用positionCaseInsensitive函数,查找字符串menu在列notes中的位置。在每个查询中执行这样操作非常耗时,因为notes内容非常多。

┌─notes─────────────────────────────────────────────────┐ 
│ wine list in Swedish; Arthur H. Rumpf Menu Collection │ 
│ wine list in Swedish; Arthur H. Rumpf Menu Collection │ 
└───────────────────────────────────────────────────────┘

直接查询SQL:

SELECT     
  dish_count,     
  status,     
  positionCaseInsensitive(notes, 'menu') AS result 
FROM menu 
GROUP BY     
  dish_count,     
  status,     
  result 
ORDER BY result DESC 
LIMIT 2 

为了避免查询时临时计算,我们增加物化列存储计算结果:

ALTER TABLE menu     
ADD COLUMN `materlized_result` Int16 MATERIALIZED positionCaseInsensitive(notes, 'menu') 

-- 增加列之后,未来插入数据会物化。但之前的数据需要执行optimise语句
OPTIMIZE TABLE menu FINAL 

下面可以直接查询物化列,读者可以对比两者性能:

SELECT     
  dish_count,     
  status,     
  materlized_result AS result 
FROM menu 
GROUP BY     
  dish_count,     
  status,     
  result 
ORDER BY result DESC 
LIMIT 2 

建议需要从大量内容列中抽取小结果时,使用物化列提升性能。

三种表达式差异

(1)数据写入:在数据写入时,只有DEFAULT类型的字段可以出现在INSERT语句中。而MATERIALIZED和ALIAS都不能被显式赋值,它们只能依靠计算取值。例如试图为MATERIALIZED类型的字段写入数据,将会得到如下的错误。

(2)数据查询:在数据查询时,只有DEFAULT类型的字段可以通过SELECT 返回。而MATERIALIZED和ALIAS类型的字段不会出现在SELECT查询的返回结果集中。

(3)数据存储:在数据存储时,只有DEFAULT和MATERIALIZED类型的字段才支持持久化。如果使用的表引擎支持物理存储(例如TinyLog表引擎),那么这些列字段将会拥有物理存储。而ALIAS类型的字段不支持持久化,它的取值总是需要依靠计算产生,数据不会落到磁盘。

### 如何在 SQL Server 中查看表字段默认值SQL Server 中,可以通过系统视图和存储过程来查询表字段默认值。以下方法提供了详细的实现方式: #### 方法一:使用 `sys.default_constraints` 系统视图 SQL Server 提供了 `sys.default_constraints` 系统视图,可以用来查询字段默认值约束信息。结合其他系统视图如 `sys.columns` 和 `sys.tables`,可以获取表字段默认值。 以下是查询的代码示例: ```sql SELECT tc.name AS TableName, c.name AS ColumnName, dc.name AS DefaultConstraintName, dc.definition AS DefaultValue FROM sys.default_constraints dc JOIN sys.columns c ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id JOIN sys.tables tc ON c.object_id = tc.object_id WHERE tc.name = 'YourTableName'; ``` 上述代码将返回指定表中所有字段默认值及其相关信息[^1]。 #### 方法二:使用 `sp_help` 存储过程 `sp_help` 是一个内置的存储过程,可以提供关于表结构的详细信息,包括字段默认值。执行以下命令即可查看表的默认值信息: ```sql EXEC sp_help 'YourTableName'; ``` 该命令会输出表的详细信息,其中包含字段默认值部分[^2]。 #### 方法三:通过 `INFORMATION_SCHEMA.COLUMNS` 查询 虽然 `INFORMATION_SCHEMA.COLUMNS` 不直接显示默认值,但可以结合 `sys.default_constraints` 使用,以获取更全面的信息。以下是示例代码: ```sql SELECT COLUMN_NAME, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'YourTableName'; ``` 此查询将返回表中字段默认值定义,但仅适用于显式定义的默认值[^3]。 ### 注意事项 - 如果字段没有设置默认值,则上述查询结果中不会显示该字段。 - 默认值可能以表达式的形式存在(例如 `GETDATE()`),因此需要解析 `definition` 列的内容以确定具体值[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值