1.大数据ClickHouse(十五):ClickHouse SQL语法之DDL 操作讲解
2.ClickHouse 系列 - 向量化执行引擎介绍
3.ClickHouse 语法详解
4.ClickHouse SQL基本语法和导入导出实战
5.大数据ClickHouse进阶(一):ClickHouse使用场景和集群安装
6.ClickHouse的索引深入了解
大数据ClickHouse(十五):ClickHouse SQL语法之DDL 操作讲解
在ClickHouse中,数据定义语言(DDL)用于管理和操作数据库结构。其中,DDL操作主要针对Merge表引擎、Distributed表引擎及MergeTree家族的表引擎,支持库、涂鸦战机源码表和字段的创建、查看、删除等。创建库时,会在/var/lib/clickhouse/metadata目录下生成库目录和库.sql文件,记录库下的建表信息。
创建表时,可以使用多种语法。直接创建表可以指定表引擎,也可以不指定,此时默认使用与当前表相同的引擎,但不会复制原表中的数据。创建表时可以创建结构与已存在表相同的新表,也可以通过Select语句生成新表结构并填充数据。
表创建后,可以通过查询查看所有表、表的定义、表的字段,以及表的结构。删除表的操作需要谨慎,不可逆。在修改表时,可以添加列、删除列、给列添加注释、修改列类型,但不能清空排序、主键、分区字段。
表重命名可以应用于各种表引擎,使得数据库结构更加灵活。分区表的操作是ClickHouse中的一大特色,支持查看分区信息、卸载分区、装载分区、删除分区、替换分区、移动分区和重置分区列。分区表允许数据按特定规则分割,提高查询效率。
在ClickHouse中,还支持创建临时表和视图。临时表是内存中的表,用于快速处理数据,而视图则可以是基于查询结果的表结构。普通视图不存储数据,仅作为查询的别名或同义词;物化视图则存储查询结果,提供持久化的数据存储,支持更新和优化性能。
临时表和视图的创建和管理简化了数据处理和查询流程,使得ClickHouse在大规模数据处理场景下更加高效。通过理解并合理使用这些特性,兴义网站源码可以构建出更高效、灵活的数据库应用。例如,通过创建临时表进行快速数据处理,使用视图简化复杂查询逻辑,以及通过分区表优化查询性能。
ClickHouse 系列 - 向量化执行引擎介绍
ClickHouse 是一款性能出色的 OLAP 计算引擎,因其列式存储与极致性能的向量化执行引擎而广受青睐。向量化执行引擎能够显著提升查询性能,其原理是将指令应用于一组数据(向量)上,实现单指令、多数据操作,利用 CPU 的数据并行性。
向量化技术通过将指令应用于数组中的元素,实现空间并行计算,从而充分利用 CPU 流水线的计算单元。CPU 提供的 SSE、AVX 等指令集支持向量化计算,例如,在 Linux 中,通过执行 `cat /proc/cpuinfo` 命令,可以查看 CPU 支持的向量化指令集。
然而,向量化并非适用于所有场景。在包含大量分支、跳转和条件判断的复杂控制流中,向量化难以实现高效执行。向量化主要适用于优化简单并行可计算场景和频繁调用的基础逻辑。
在实现向量化时,有多种方法可供选择,包括嵌入式汇编、使用内置函数、Cilk 库、编译器制导语句、编译器自动向量化、以及使用高性能库。其中,自动向量化和内置函数因其通用性和易用性而被 OLAP 系统广泛采用。
以 SSE__mm_add_ps 内置函数为例,该函数允许一次性计算 8 个单精度浮点数的加法。此外,经过编译器优化的代码可能会自动使用向量化指令,如上图所示,展示了一个数组求和的代码经过编译器优化后的汇编代码,其中包括了大量的向量化指令。
在 ClickHouse 中,向量化执行主要通过 SIMD 内置函数和编译器自动向量化实现。大量的 SIMD 内置函数用于优化关键代码路径,而 Pipeline 执行引擎的设计使得数据按列处理,为编译器生成良好的向量化代码提供了基础。
例如,ClickHouse 中使用 SIMD 内置函数优化了 Filter 处理,该过滤器用于表示 WHERE 和 HAVING 子句的条件和真值。通过压缩和向量化计算,提高了性能。
编译器自动向量化是 ClickHouse 实现向量化的关键方法。Pipeline 执行引擎是威廉原始源码 ClickHouse 的核心,按列处理数据,使得向量化能够有效发挥。为了提高向量化能力,ClickHouse 通过代码设计、模板使用、内联函数、减少虚函数调用等方法进行优化。
在介绍 Pipeline 执行引擎实现前,让我们先了解一下 ClickHouse 中 SQL 执行流程。提交的 SQL 查询首先解析成抽象语法树(AST),然后通过一系列优化生成物理执行计划,即 QueryPlan。QueryPlan 由多个 QueryStep 构成,最终创建 QueryPipeline,执行器基于优化后的 QueryPlan 调度执行。
QueryPipeline 是 ClickHouse Pipeline 的基本结构,一个有向无环图,由 Processor 节点和 Port 端口组成。Processor 处理数据,Port 用于数据流通。Source 和 Sink 是特殊的 Processor,分别有一个输出端口和输入端口。
下面以具体 SQL 为例,展示 ClickHouse Pipeline 的结构,包括数据读取、过滤、表达式计算等步骤。整个 Pipeline 从 Source 开始,到 Sink 结束,通过处理器依次处理数据,最终输出结果。
传统火山模型计算模式在数据流与控制流绑定,缺乏灵活性和高效性。而 ClickHouse Pipeline 将数据流与控制流分离,采用独立线程池执行 Processor,实现异步调度,优化资源利用和并行处理。
ClickHouse Pipeline 具有动态扩展能力,在执行过程中可以创建新的 Processor。聚合执行分为 consume 和 generate 阶段,分别对数据进行预聚合和最终聚合,以提高性能。
表达式求值是 ClickHouse Pipeline 的重要组成部分,通过 ActionsDAG 实现。ActionsDAG 是一个有向无环图,包含不同类型的节点,如输入列、常量列、别名、函数等。拓扑排序和按列计算的策略使表达式计算更加灵活高效。
在 ClickHouse 中,可以使用 EXPLAIN 查询查看执行的 Pipeline 和 ActionsDAG,提供执行流程的详细信息,帮助理解查询执行的优化策略。
综上所述,ClickHouse 的kkfileview源码阅读向量化执行引擎通过大量使用 SIMD 内置函数、高效的 Pipeline 执行引擎设计与实现,以及优化的表达式求值策略,共同构建起卓越的查询性能。
ClickHouse 语法详解
ClickHouse 采用两种解析器处理 SQL 查询,分别是完整 SQL 解析器(递归式)和数据格式解析器(快速流式)。在非 INSERT 查询中,仅使用完整 SQL 解析器。对于 INSERT 查询,同时使用两种解析器:完整 SQL 解析器处理包含 "INSERT INTO t VALUES" 的部分,快速流式解析器解析数据,如 (1, 'Hello, world'), (2, 'abc'), (3, 'def') 等。可以通过设置参数 input_format_values_interpret_expressions 来开启对数据部分的完整 SQL 解析器支持。当此参数为 1 时,ClickHouse 将优先使用快速流式解析器解析数据,若失败则尝试完整 SQL 解析器,处理数据如同表达式。
数据可以采用任意格式。接收到请求时,服务端会在内存中计算不超过 max_query_size(默认为 1 mb)的请求数据部分,剩余部分则交给快速流式解析器。当使用 INSERT 语句的 Values 格式时,数据部分的解析与 SELECT 中表达式的解析看似相同,但实际上存在诸多限制。
本文主要覆盖完整 SQL 解析器的相关内容。关于数据格式解析的更多详情,请参阅“格式”章节。SQL 语句中的语法结构部分(如标识符、符号间)允许包含任意空白字符,包括空格、制表符、换行符等。ClickHouse 支持 SQL 风格或 C 语言风格的注释。
关键字在特定场景中是不区分大小写的,例如在系统表 system.data_type_families 中检查数据类型名称时。所有其他关键字则区分大小写,包括函数名称。关键字仅在相应的上下文中被认为是关键字,如果需要使用与关键字同名的标识符,应使用双引号或反引号包含它们。
标识符包括变量名和字符。变量名推荐不被括起,但必须遵循正则表达式^[a-zA-Z_][0-9a-zA-Z_]*$,且不能与关键字相同,如 "x", "_1", "X_y__Z_" 等。若需使用关键字同名或包含其他符号的变量名,应使用双引号或反引号,例如:"id", `id`。
字符包含数字、字母、括号、NULL 值等。数字类型字符的值类型为最小数据类型。例如,1 解析为 UInt8, 解析为 UInt。字符串仅支持用单引号包含,并通过反斜杠进行转义,osstart的源码如 \b, \f, \r, \n, \t, \0, \a, \v, \xHH。复合字符串使用方括号或圆括号构造,实际并非字符串,而是包含创建数组和元组运算符的表达式。NULL 值表示不存在的值,必须在字段声明为“空值”类型,其表现形式依赖于输入或输出数据格式。
函数调用类似于标识符后跟圆括号包含的参数列表,且圆括号是必需的,无论参数列表是否为空。函数分为常规函数和聚合函数,后者可能包含两个参数列表,第一个参数列表称为“参数”。别名是用户对表达式的自定义名称,但在当前查询或子查询中是全局可见的,且在不同子查询中不可见。星号可代替表达式使用于 select 查询中,表示所有列。表达式是函数、标识符、字符、运算符的语句、括号中的表达式、子查询或星号。表达式列表由逗号分隔,而函数和运算符可以将表达式作为参数。
ClickHouse SQL基本语法和导入导出实战
ClickHouse SQL基本语法和导入导出实战
ClickHouse的SQL世界里,SQL语法和数据管理是核心。让我们一步步探索:1. SQL基本语法
创建数据库与表:数据库是命名空间,通过CREATE DATABASE确保数据结构清晰。创建表有三种方式:直接、复制其他表结构或使用SELECT子句填充。表字段可指定默认值,但修改默认值有限制,尤其是主键字段和特定表引擎。
分区表: ClickHouse支持分区表,通过PARTITION BY指定分区键,如年月,能提升查询性能。分区键设计需根据查询场景,精细分区可提高效率,但过细可能导致性能下降。
视图: ClickHouse有普通和物化视图,普通视图仅是查询代理,而物化视图像触发器,会保存数据。
ALTER: MergeTree等引擎支持ALTER,如添加字段、更改数据类型和移动数据表,但注意数据表移动需在同一节点内。
2. 导入导出
INSERT INTO用于添加数据,支持VALUES和SELECT语法,而UPDATE和DELETE在ClickHouse中用于Mutation操作,不支持完全意义上的UPDATE和DELETE,且不支持事务和回滚。总结
ClickHouse的SQL语法和数据管理提供了高效的数据操作和管理手段,包括数据库和表的创建、分区表的优化、视图的使用以及数据的导入导出。理解并掌握这些基础操作,是有效利用ClickHouse的关键。大数据ClickHouse进阶(一):ClickHouse使用场景和集群安装
ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS),支持实时生成分析报告和使用SQL查询。它最初作为Yandex.Metrica产品用于WEB流量分析。ClickHouse具有C++编写,拥有多项优势如完备的DBMS功能、列式存储、数据压缩、向量化执行、支持标准SQL、多张表引擎、多线程与分布式、多主架构、交互式查询、数据分片与分布式查询等。它适合于OLAP数据分析,数据量越大,性能优势越明显。 在使用场景方面,ClickHouse适用于大数据分析、实时数据处理、在线报告生成等需求。但不适合小规模数据处理或事务性操作。 对于ClickHouse的集群安装,我们以ClickHouse .9.4.版本为例,采用rmp包的方式进行。首先,从官网下载最新的rpm安装包,地址为:https://repo.yandex.ru/ClickHouse/rpm/stable/x_/。此版本起,仅需下载3个rpm包。 安装流程如下: 1. 选择三台节点,即node1、node2、node3,分别安装ClickHouse所需rpm包。 2. 安装并启动Zookeeper集群,用于实现集群副本之间的同步。 3. 配置外网访问权限,修改/etc/ClickHouse-server/config.xml文件中第行内容,允许外部访问。 4. 在每台节点创建并配置metrika.xml文件,用于创建分布式表时的分片与副本配置。需确保metrika.xml上级目录拥有者权限为ClickHouse,并将文件放置于/etc/ClickHouse-server/config.d路径下。 5. 启动ClickHouse服务,检查集群配置是否完成,通过ClickHouse客户端查询集群信息。 安装完成后,ClickHouse将生成配置文件目录、数据存储目录、日志目录。服务端配置文件包括全局配置和用户配置。数据存储目录和日志目录通常需根据实际情况修改,以确保数据安全与高效存储。 通过上述步骤,成功搭建ClickHouse分布式集群,适用于大规模数据分析场景。ClickHouse的索引深入了解
一、一级索引
在MergeTree中,PRIMARY KEY 主键不仅用于去重,还用于构建索引,以此提升查询效率。MergeTree会根据index_granularity间隔(默认为行)为数据表生成一级索引,并保存至primary.idx文件中。这些索引数据按照PRIMARY KEY 排序,通常通过ORDER BY 方式指定主键。
稀疏索引
primary.idx文件内的一级索引采用稀疏索引实现。稀疏索引与稠密索引的主要区别在于:在稠密索引中,每一行索引标记都对应一行具体的数据记录;而在稀疏索引中,每一行索引标记对应的是一段数据,而非单行。稀疏索引的优势在于,仅需使用少量索引标记就能记录大量数据区间位置信息,数据量越大,其优势越明显。在MergeTree系列引擎表中,对应的primary.idx文件就是稀疏索引,由于稀疏索引占用空间小,所以其索引数据常驻内存。
索引粒度
在ClickHouse MergeTree引擎中,默认的索引粒度是,参数为index_granularity。一般情况下,我们不会修改此值,按照默认即可。我们可以通过以下sql语句查看每个MergeTree引擎表对应的index_granularity的值:
node1 :) show create table t_mt;
1.
索引粒度对于MergeTree表引擎至关重要,可以根据整个数据的长度,按照索引粒度对数据进行标注,然后抽取对应的数据形成索引。
索引形成过程
表数据以index_granularity的粒度(默认)被标记成多个小区间,其中每个区间最多行数据,每个区间标记后形成一个MarkRange,通过start和end表示MarkRange的具体范围,数据文件也会按照index_granularity的间隔粒度生成压缩数据块。由于是稀疏索引,MergeTree需要间隔index_granularity行数据生成一条索引,同时对应一个索引编号,每个MarRange与一个索引编号对应,通过与start及end对应的索引编号的取值,可以得到对应的数值区间;索引编号对应的索引值会依据声明的主键字段获取,最终索引编号和索引值被写入primary.idx文件中保存。
假设现在有一份测试数据,共行记录,其中主键ID为String类型,ID值从A开始,后面依次为A、A...直到A为止,假设我们设置MergeTree的索引粒度index_granularity=3,根据索引的生成规则,primary.idx文件内的索引数据如下:
根据索引数据,MergeTree将此数据片段划分成/3=个小的MarkRange,其中所有MarkRange的最大数值区间为[A,+inf),划分的MarkRange如下:
索引查询过程
使用索引查询其实是对两个数值区间的交集判断,其中一个区间是基于主键的查询条件转换而来的条件区间,而另一个区间是上图中MarkRange对应的数值区间。
整个索引查询的过程大致分为3个步骤:
1、生成查询条件区间
查询时首先将查询条件转换为条件区间,即便是单个值的查询条件也会转换成区间的形式,例如:
2、递归交集判断
以递归的方式依次对MarkRange的数值区间与条件区间做交集判断,从最大的区间[A,+inf)开始:
如果不存在交集,则直接忽略掉整段MarkRange
如果存在交集,且MarkRange步长大于8(end-start),则将此区间进一步拆分成8个区间(由merge_tree_coarse_index_granularity指定,默认值为8),并重复此规则,继续做递归交集判断。
如果存在交集,且MarkRange不可再分解(步长小于8),则记录MarkRange并返回。
3、合并MarkRange区间
将最终匹配的MarkRange聚在一起,合并他们的范围。
当查询条件WHERE ID ='A'的时候,最终读取[A,A)和[A,A]两个区间的数据即可,他们对应的MarkRange(start:0,end:2)范围,而无其他无用的区间都被裁剪过滤掉,因为MarkRange转换的数值区间是闭区间,所以会额外匹配到临近的一个区间,完整的逻辑图如下图所示:
二、二级索引(跳数索引)
除了一级索引外,MergeTree还支持二级索引,也称为跳数索引,它由数据的聚合信息构建而成,根据索引类型的不同,其聚合信息的内容也不同。跳数索引的目的与一级索引一样,即帮助查询时减少数据扫描的范围。
跳数索引需要在Create语句内定义,完整语法如下:
1.
对以上参数的解释如下:
index_name:定义的二级索引名称
index_type:跳数索引类型,最常用就是minmax索引类型。minmax索引记录了一段数据内的最小和最大极值,其索引的作用类似分区目录,能够快速跳过无用的数据区间。
granularity:定义聚合信息汇总的粒度。
与一级索引一样,如果在建表语句中声明了跳数索引,则会在路径“/var/lib/ClickHouse/data/DATABASE/TABLE/PARTITION/”目录下生成索引与标记文件(skp_idx.idx与skp_idx.mrk)。
在接触跳数索引时,很容易将index_granularity与granularity概念混淆,对于跳数索引而言,index_granularity定义了数据的粒度,而granularity定义了聚合信息汇总的粒度,也就是说,granularity定义了一行跳数索引能够跳过多少个index_granularity区间的数据。
minmax跳数索引的生成规则
minmax跳数索引聚合信息是在一个index_granularity区间内数据的最小和最大极值。首先,数据按照index_granularity粒度间隔将数据划分成n段,总共有[0~n-1]个区间(n=total_rows/index_granularity,向上取整),接着根据跳数索引从0区间开始,依次按index_granularity粒度从数据中获取聚合信息,每次向前移动1步,聚合信息逐步累加,最后当移动granularity次区间时,则汇总并生成一行跳数索引数据。
以下图为例:假设index_granularity=且granularity=3,则数据会按照index_granularity划分成n等份,MergeTree从第0段分区开始,依次获取聚合信息,当获取到第3个分区时(granularity=3),则汇总并生成第一行minmax索引(前3段minmax极值汇总后取值为[1,9])。
minmax跳数索引案例:
#删除表 t_mt
#重新创建t_mt表,包含二级索引
#插入数据
#查看数据分区路径
ClickHouse内幕(1)数据存储与过滤机制
ClickHouse内部细节:数据存储与过滤机制详解
ClickHouse的数据管理关键在于其存储结构和高效的过滤机制。首先,数据存储采用基于分区的目录结构,每个表按分区键(如日期)划分为多个Part,存储在统一目录下,每个Part包含主键索引文件(primary.idx)、列元数据文件、数据文件(bin)以及校验文件等。 索引结构是基础,每个Part都构建了一个完整的列式索引,通过排序和稀疏索引(Mark)组织数据。以(date, city, action)为例,索引列用于排序和分区裁剪,Mark则标记数据块,简化查询时的数据定位。 过滤机制在数据读取阶段起作用。在SQL编译阶段,ClickHouse分析查询需求,确定需要读取的Part及其Mark列表。KeyCondition是核心算法,它判断范围矩阵是否满足过滤条件,通过RPN表达式进行高效计算。 Part裁剪是初次过滤,通过minmax_idx_condition和partition_pruner两个条件,根据分区键和表达式范围进行筛选。Mark裁剪则进一步细化,将MarkRange转换为范围矩阵,利用KeyCondition进行过滤。 Row过滤是查询执行阶段,通过ColumnVector::filter实现,使用SIMD技术进行优化,如Filter Mask和SIMD版本的过滤,以提高性能。性能优化考虑了复用Filter Mask、利用数据局部有序性以及合理利用SIMD指令的效率。ClickHouse:联接执行的内部机制
在之前的文章中,我们回顾了 ClickHouse 中可用的 SQL JOIN 类型。在本文中,我们将探索 ClickHouse 中联接执行的内部结构,以便优化应用程序使用的查询的联接。ClickHouse 中的查询以高度并行的方式处理,占用当前服务器上可用的所有必要资源,并且在许多情况下,利用硬件达到其理论极限。
查询管道确定每个查询执行阶段的并行级别。下图显示了 ClickHouse 查询管道如何在具有四个 CPU 内核的服务器上处理查询:
查询的表数据动态分布在四个独立的并行流阶段,这些阶段将数据按块流式传输到 ClickHouse。
大部分查询处理阶段由四个线程并行执行,使用的线程数量取决于max_threads 设置,默认设置为 ClickHouse 在其运行的机器上看到的 CPU 核心数。
对于所有查询(包括连接),查询管道确保以高度并行和可扩展的方式处理表数据。
为了确保资源的最大利用率,ClickHouse 开发了六种不同的连接算法。这些算法决定了连接查询的规划和执行方式。ClickHouse 可以被配置为在运行时自适应地选择最佳的连接算法,并动态地改变使用的算法(取决于资源的可用性和使用情况)。用户也可以指定所需的连接算法。
本文将详细描述并比较基于内存哈希表的三种 ClickHouse 连接算法:哈希连接、并行哈希连接和 Grace 哈希连接。
哈希连接算法是速度最快且最通用的连接算法。它使用内存中的哈希表来查找连接,适合无法或不可行利用表排序的情况。并行哈希连接算法可以在右表很大的情况下更快,但需要更多的内存。Grace 哈希连接算法是一种非内存限制的版本,将数据临时溢出到磁盘上,不需要对数据进行排序,从而克服了其他连接算法(如部分合并连接算法)的性能挑战。
对于所有示例查询,我们将使用规范化 IMDB 数据集中的两个表。为了拥有可观的数据进行测试,我们在新数据库中生成了这些表的大型版本。所有的可视化中,人为地将 ClickHouse 查询管道中使用的并行级别限制为 max_threads = 2。在所有的示例查询运行中,我们使用默认的 max_threads 设置,即 ClickHouse 在运行的机器上看到的 CPU 核心数。在本节中,我们将开始探索 ClickHouse 连接算法,从最通用的哈希连接算法开始。
哈希连接算法非常快速,查找能力强大,使内存中的哈希表成为 ClickHouse 中实现连接的自然通用选择。哈希连接算法是 ClickHouse 中可用的连接实现中最通用的,可以支持所有连接类型和严格性设置。并行哈希连接算法通过同时构建多个哈希表,可以更快地处理具有大右侧表的查询,但需要更多的内存。
Grace 哈希连接算法是一种非内存绑定版本,将输入数据分成多个 bucket,其中一些 bucket 在处理之前会被暂存在磁盘上,然后在内存中按顺序处理。以下图表总结了本文中所有连接查询运行的内存消耗和执行时间(将 max_threads 设置为 ,右侧表更大)。