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

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

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类型的字段不支持持久化,它的取值总是需要依靠计算产生,数据不会落到磁盘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值