文章目录
- [1. ClickHouse 表结构设计](#1. ClickHouse 表结构设计)
-
- [1. 表的创建](#1. 表的创建)
-
- 与标准SQL的差异
- [1. 创建普通表](#1. 创建普通表)
- [2. 创建物化视图](#2. 创建物化视图)
- [3. 创建分布式表](#3. 创建分布式表)
- [2. 表引擎](#2. 表引擎)
-
- [1. MergeTree:](#1. MergeTree:)
- [2. Log:](#2. Log:)
- [3. Memory:](#3. Memory:)
- [4. Distributed:](#4. Distributed:)
- [5. Kafka:](#5. Kafka:)
- [6. MaterializedView:](#6. MaterializedView:)
- [7. File和URL:](#7. File和URL:)
- [3. MergeTree 家族](#3. MergeTree 家族)
-
- [3.1. MergeTree:](#3.1. MergeTree:)
- [3.2. ReplacingMergeTree:](#3.2. ReplacingMergeTree:)
- [3.3. SummingMergeTree:](#3.3. SummingMergeTree:)
- [3.4. AggregatingMergeTree:](#3.4. AggregatingMergeTree:)
- [3.5. CollapsingMergeTree:](#3.5. CollapsingMergeTree:)
- [3.6. VersionedCollapsingMergeTree:](#3.6. VersionedCollapsingMergeTree:)
- [4. Log 家族](#4. Log 家族)
-
- [4.1. TinyLog:](#4.1. TinyLog:)
- [4.2. StripeLog:](#4.2. StripeLog:)
- [4.3. Log:](#4.3. Log:)
- [5. Memory 和 File 家族](#5. Memory 和 File 家族)
-
- [5.1. Memory:](#5.1. Memory:)
- [5.1.2. File:](#5.1.2. File:)
- [6. Null 家族](#6. Null 家族)
- [7. 外部数据表引擎(MySQL, HDFS, URL, etc.)](#7. 外部数据表引擎(MySQL, HDFS, URL, etc.))
-
- [7.1. MySQL:](#7.1. MySQL:)
- [7.2. HDFS:](#7.2. HDFS:)
- [7.3. URL:](#7.3. URL:)
- [8. 分区和分片](#8. 分区和分片)
-
- [8.1. 什么是分区和分片](#8.1. 什么是分区和分片)
- [8.2. 如何设置分区和分片](#8.2. 如何设置分区和分片)
- [9. 使用索引](#9. 使用索引)
- [9.1. 什么是ClickHouse表索引](#9.1. 什么是ClickHouse表索引)
- [9.2. 如何创建和使用索引:](#9.2. 如何创建和使用索引:)
- [2. ClickHouse 表结构优化](#2. ClickHouse 表结构优化)
-
- [1. 数据去重](#1. 数据去重)
- [2. 数据排序](#2. 数据排序)
- [3. 数据抽样](#3. 数据抽样)
1. ClickHouse 表结构设计
1. 表的创建
在ClickHouse中,创建表的基本语法如下:
sql
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
) ENGINE = engine
其中:
table_name
是要创建的表的名称。column1, column2, ...
是表的列的名称,datatype
是各列的数据类型。ENGINE
是表引擎的名称。在ClickHouse中,表引擎决定了数据的存储和索引方式。
例如,以下是一个创建名为users
的表的示例,该表有id
(整数类型,主键),name
(字符串类型),age
(整数类型)和country
(字符串类型)的列:
sql
CREATE TABLE users (
id Int32,
name String,
age Int32,
country String
) ENGINE = MergeTree()
ORDER BY id
与标准SQL的差异
虽然 ClickHouse 支持 SQL,但由于它是一个为了解决特定问题(例如,处理大数据和实时分析)而设计的数据库,因此它的 SQL 有一些特殊之处,包括在创建表时:
-
表引擎:在创建表的语句中,需要指定表引擎。这是 ClickHouse 的一项独特功能,表引擎决定了数据的存储方式和可用的查询处理。在标准 SQL 中,通常不需要指定表引擎。
-
排序顺序:在创建表的语句中,可以指定排序键,它决定了数据在磁盘上的排序顺序。在标准 SQL 中,数据的物理排序通常是不透明的。
-
数据类型:ClickHouse 支持一些标准 SQL 中没有的数据类型,例如
Array
,Tuple
,Map
,UUID
等。 -
主键和索引:与标准 SQL 不同,ClickHouse 不强调主键的概念,实际上,主键在 ClickHouse 中主要用于数据分区和执行数据采样查询。此外,ClickHouse 支持更灵活和强大的索引类型。
-
分区:ClickHouse 支持表分区,允许将数据在物理级别(例如,不同的磁盘或文件系统)上分割为更小、更易于管理的部分。这在标准 SQL 中不常见。
1. 创建普通表
普通表在ClickHouse中是最基础的数据存储结构。创建普通表需要定义列的名称和数据类型,以及使用的表引擎。最常用的表引擎是MergeTree。
创建普通表的SQL语句:
sql
CREATE TABLE test_table (
id UInt32,
name String,
age UInt8
) ENGINE = MergeTree()
ORDER BY id;
此表test_table
有三列,分别是id
(32位无符号整数)、name
(字符串)和age
(8位无符号整数)。表引擎是MergeTree,按id
进行排序。
2. 创建物化视图
物化视图是一种特殊的表,它保存了基本表查询的结果。与普通视图不同,物化视图的数据是实际存储在磁盘上的,所以查询物化视图通常比查询基表要快。
创建物化视图的SQL语句:
sql
CREATE MATERIALIZED VIEW mv_test_table AS
SELECT
name,
avg(age) as avg_age
FROM test_table
GROUP BY name;
此物化视图mv_test_table
保存了test_table
中每个name
的平均age
。
3. 创建分布式表
分布式表是ClickHouse中的一个特殊表,它可以将数据存储在多个节点上。创建分布式表需要指定集群、数据库、基表和分片键。
创建分布式表的SQL语句:
sql
CREATE TABLE dist_test_table AS test_table
ENGINE = Distributed('test_cluster', '', 'test_table', rand());
此分布式表dist_test_table
将数据在名为test_cluster
的集群上分配,基表是test_table
,使用rand()
函数作为分片键,即随机分配数据到各个节点上。
2. 表引擎
1. MergeTree:
说明:MergeTree是ClickHouse的主要表引擎,支持索引和数据分区,适用于大数据计算。
使用场景:适用于大数据分析,如用户行为分析、日志分析等。
示例:
sql
CREATE TABLE example_merge_tree
(
date Date,
id UInt32,
value String
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, id)
SETTINGS index_granularity = 8192;
2. Log:
说明:Log表引擎用于存储日志和其他机器数据。不支持索引和数据分区。
使用场景:适用于小数据量的日志和其他机器数据的存储。
示例:
sql
CREATE TABLE example_log
(
event_time DateTime,
event_type String,
event_data String
) ENGINE = Log;
3. Memory:
说明:Memory表引擎将所有数据存储在RAM中,适用于临时表和小数据量。
使用场景:适用于需要快速访问和计算的小数据量场景。
示例:
sql
CREATE TABLE example_memory
(
key UInt32,
value String
) ENGINE = Memory;
4. Distributed:
说明:Distributed表引擎用于在多个节点间分布查询和数据。它自动分发查询和数据到所有节点。
使用场景:适用于需要在多个节点间进行数据分析的分布式场景。
示例:
sql
CREATE TABLE example_distributed
(
date Date,
id UInt32,
value String
) ENGINE = Distributed('my_cluster', 'my_database', 'example_merge_tree', rand());
5. Kafka:
说明:Kafka表引擎用于和Kafka集成,可用于实时数据流处理。
使用场景:适用于实时数据处理,如日志实时处理、实时数据分析等。
示例:
sql
CREATE TABLE example_kafka
(
event_time DateTime,
event_type String,
event_data String
) ENGINE = Kafka()
SETTINGS
kafka_broker_list = 'localhost:9092',
kafka_topic_list = 'test_topic',
kafka_group_name = 'test_group',
kafka_format = 'JSONEachRow',
kafka_num_consumers = 2;
6. MaterializedView:
说明:MaterializedView引擎用于预处理数据,可以提高查询性能。
使用场景:适用于需要对大数据进行预处理以提高查询性能的场景。
示例:
sql
CREATE MATERIALIZED VIEW example_mv
ENGINE = AggregatingMergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, id)
AS
SELECT
date,
id,
count() AS count
FROM example_merge_tree
GROUP BY date, id;
7. File和URL:
说明:File和URL表引擎用于对文件进行操作,例如CSV、Parquet等。
使用场景:适用于需要对文件进行操作的场景,如ETL操作、数据导入导出等。
示例:
sql
CREATE TABLE example_file
(
id UInt32,
value String
) ENGINE = File(CSV, '/path/to/your/csv_file.csv');
CREATE TABLE example_url
(
id UInt32,
value String
) ENGINE = URL('http://example.com/data.csv', CSV);
3. MergeTree 家族
ClickHouse的MergeTree家族引擎是一组支持实时数据更新、查询和数据合并功能的表引擎。这些引擎为大数据场景提供了高性能的解决方案。以下是MergeTree家族的主要成员及其使用场景。
MergeTree家族引擎根据不同的业务场景提供了多种实时数据处理功能,为大数据场景下的实时计算提供了强大的支持。在进行数据建模时,可以根据具体需求选择合适的MergeTree引擎。
3.1. MergeTree:
说明:MergeTree是ClickHouse的基本表引擎,支持索引和数据分区。
使用场景:适用于大数据分析,如用户行为分析、日志分析等。
示例:
sql
CREATE TABLE example_merge_tree
(
date Date,
id UInt32,
value String
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, id)
SETTINGS index_granularity = 8192;
3.2. ReplacingMergeTree:
说明:ReplacingMergeTree用于实时删除重复数据。当合并过程中发现相同的主键数据时,只保留最新的一条记录。
使用场景:适用于需要实时删除重复数据的场景,如实时去重、数据清洗等。
示例:
sql
CREATE TABLE example_replacing_merge_tree
(
date Date,
id UInt32,
value String
) ENGINE = ReplacingMergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, id)
SETTINGS index_granularity = 8192;
3.3. SummingMergeTree:
说明:SummingMergeTree用于实时对数值型字段进行求和。在合并过程中,具有相同主键的记录将被合并为一条记录,并对指定字段求和。
使用场景:适用于需要对数值型字段进行实时求和的场景,如计数器、流量统计等。
示例:
sql
CREATE TABLE example_summing_merge_tree
(
date Date,
id UInt32,
value UInt32
) ENGINE = SummingMergeTree(value)
PARTITION BY toYYYYMM(date)
ORDER BY (date, id)
SETTINGS index_granularity = 8192;
3.4. AggregatingMergeTree:
说明:AggregatingMergeTree用于实时对数据进行聚合。在合并过程中,具有相同主键的记录将被聚合为一条记录,根据指定的聚合函数进行计算。
使用场景:适用于需要实时聚合数据的场景,如统计、报表等。
示例:
sql
CREATE TABLE example_aggregating_merge_tree
(
date Date,
id UInt32,
value UInt32,
countState AggregateFunction(count)
) ENGINE = AggregatingMergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, id)
SETTINGS index_granularity = 8192;
3.5. CollapsingMergeTree:
说明:CollapsingMergeTree用于实时删除重复数据。不同于ReplacingMergeTree,它使用一个名为Sign的列来表示记录的状态(1表示插入,-1表示删除)。在合并过程中,符号相反且其他列相同的记录会被抵消。
使用场景:适用于需要实时删除重复数据的场景,如数据同步、状态更新等。
示例:
sql
CREATE TABLE example_collapsing_merge_tree
(
date Date,
id UInt32,
value String,
sign Int8
) ENGINE = CollapsingMergeTree(sign)
PARTITION BY toYYYYMM(date)
ORDER BY (date, id)
SETTINGS index_granularity = 8192;
3.6. VersionedCollapsingMergeTree:
说明:VersionedCollapsingMergeTree与CollapsingMergeTree类似,但它还使用一个名为Version的列来表示记录的版本。在合并过程中,版本较新的记录会覆盖版本较旧的记录。
使用场景:适用于需要实时删除重复数据并支持版本控制的场景,如数据历史记录、状态更新等。
示例:
sql
CREATE TABLE example_versioned_collapsing_merge_tree
(
date Date,
id UInt32,
value String,
sign Int8,
version UInt32
) ENGINE = VersionedCollapsingMergeTree(sign, version)
PARTITION BY toYYYYMM(date)
ORDER BY (date, id)
SETTINGS index_granularity = 8192;
4. Log 家族
ClickHouse的Log家族引擎是一组专门用于大数据日志处理的表引擎。这些引擎能够快速地处理大量日志数据,并以极高的性能对其进行查询。以下是Log家族的主要成员及其使用场景。
4.1. TinyLog:
说明:TinyLog是一种非常简单的引擎,它将所有列保存在一个文件中。不支持索引,所以查询速度较慢,但是插入速度快。
使用场景:适用于小型数据集和日志记录。
示例:
sql
CREATE TABLE example_tinylog
(
date Date,
id UInt32,
value String
) ENGINE = TinyLog;
4.2. StripeLog:
说明:StripeLog在存储结构上类似于TinyLog,但是数据分为几个部分(stripes)进行存储,每个stripe对应一个块(block)。不支持索引。
使用场景:适用于较大的日志记录。
示例:
CREATE TABLE example_stripelog
(
date Date,
id UInt32,
value String
) ENGINE = StripeLog;
4.3. Log:
说明:Log是一种简单的引擎,它把每一列的数据分别存储在不同的文件中。不支持索引,适用于大量的日志数据。
使用场景:适合大量的日志记录和流数据。
示例:
sql
CREATE TABLE example_log
(
date Date,
id UInt32,
value String
) ENGINE = Log;
总结:Log家族引擎特别适合处理大量的日志数据,能够以极高的效率插入和查询数据。但是由于这些引擎不支持索引,所以查询性能会比MergeTree家族的引擎要差一些。在进行数据建模时,可以根据数据量和查询需求选择合适的Log引擎。
5. Memory 和 File 家族
ClickHouse中的Memory和File家族引擎分别用于在内存和文件系统中存储数据。以下是Memory和File家族的主要成员及其使用场景。
5.1. Memory:
说明:Memory引擎将所有数据存储在内存中。它支持实时查询,并且具有极高的查询速度。但是,由于它将所有数据保存在内存中,因此在服务器重启或崩溃时,数据会丢失。
使用场景:适用于需要快速查询的小型数据集,如缓存、临时表或实时分析。
示例:
sql
CREATE TABLE example_memory
(
date Date,
id UInt32,
value String
) ENGINE = Memory;
5.1.2. File:
说明:File引擎将数据保存在服务器的文件系统中。它支持将数据存储为各种文件格式(如CSV、Parquet、JSON等)。File引擎不支持索引,因此查询速度较慢。
使用场景:适用于需要将数据以特定文件格式存储的场景,如ETL操作、数据备份或离线分析。
示例:
sql
CREATE TABLE example_file
(
date Date,
id UInt32,
value String
) ENGINE = File(CSV);
总结:Memory和File家族引擎分别用于内存和文件系统中的数据存储。Memory引擎具有非常高的查询速度,适用于实时查询,但数据在服务器重启或崩溃时会丢失。File引擎适用于需要将数据存储为特定文件格式的场景,但查询速度较慢。在进行数据建模时,可以根据数据存储需求和查询需求选择合适的Memory或File引擎。
6. Null 家族
Null家族是ClickHouse中的一个特殊的表引擎家族,它基本上不会执行任何操作或存储任何数据。以下是Null家族的主要成员及其使用场景:
- Null:
说明:Null引擎不保存数据,并且不对数据进行任何操作。当你往这个表里面插入数据时,数据会被直接丢弃。对于从这个表中的查询,它总是返回一个空结果。
使用场景:Null引擎主要用于调试或测试,例如,你可能想要测试插入或查询的性能,而不实际保存任何数据。另一个常见用例是作为一个"黑洞"表,用来快速丢弃不需要的数据。
示例:
sql
CREATE TABLE example_null
(
date Date,
id UInt32,
value String
) ENGINE = Null;
总结:Null家族引擎基本上不执行任何操作,也不保存任何数据。尽管Null引擎在生产环境中的应用可能有限,但在调试和测试中可能很有用。
7. 外部数据表引擎(MySQL, HDFS, URL, etc.)
ClickHouse支持外部数据表引擎,这些引擎可以让你以类似于操作本地表的方式访问外部数据源。以下是一些常见的外部数据表引擎及其特点:
7.1. MySQL:
说明:MySQL表引擎允许你将MySQL数据库中的数据表作为ClickHouse本地表进行操作。这使得你可以方便地在ClickHouse中查询MySQL表数据。
使用场景:当你需要在ClickHouse中查询MySQL中的数据时,MySQL表引擎非常有用。
示例:
sql
CREATE TABLE mysql_table
(
id UInt32,
name String,
age UInt8
) ENGINE = MySQL('host:port', 'database_name', 'table_name', 'user', 'password');
7.2. HDFS:
说明:HDFS表引擎可以让你将Hadoop分布式文件系统(HDFS)中的数据表作为ClickHouse本地表进行操作。它支持各种文件格式,如Parquet、ORC、Avro等。
使用场景:当你需要在ClickHouse中查询HDFS中的数据时,HDFS表引擎非常有用。
示例:
sql
CREATE TABLE hdfs_table
(
id UInt32,
name String,
age UInt8
) ENGINE = HDFS('hdfs://host:port/path/to/data/file.parquet', 'Parquet');
7.3. URL:
说明:URL表引擎可以让你将远程文件(通过HTTP或HTTPS访问)作为ClickHouse本地表进行操作。它支持各种文件格式,如CSV、TSV、JSON等。
使用场景:当你需要在ClickHouse中查询远程文件中的数据时,URL表引擎非常有用。
示例:
sql
CREATE TABLE url_table
(
id UInt32,
name String,
age UInt8
) ENGINE = URL('https://example.com/data.csv', 'CSV', 'id UInt32, name String, age UInt8');
总结:外部数据表引擎可以让你方便地访问外部数据源,如MySQL、HDFS或URL等。这使得在ClickHouse中整合和查询多种数据源变得简单。
8. 分区和分片
分区和分片是在数据库中进行数据管理的两种常见技术,它们在ClickHouse中也有所应用。
- 分区 (Partitioning):
- 分区是一种将数据表分解成更小、更易于管理的部分的技术。在ClickHouse中,你可以基于一个或多个列的值将表分区。每个分区可以单独进行操作,例如删除或合并。
- 在创建表时,可以使用
PARTITION BY
子句定义分区键。例如,如果你有一个包含用户活动记录的表,你可能希望根据时间将数据分区,这样就可以轻松地删除旧的数据。
示例:
sql
CREATE TABLE events
(
date Date,
event_id UInt32,
user_id UInt32,
...
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, event_id, user_id);
- 分片 (Sharding):
- 分片是一种将数据分散到多个服务器的技术,以便有助于提高性能和可扩展性。在ClickHouse中,你可以使用分布式表引擎来实现分片。
- 在创建分布式表时,你需要指定一个集群配置,以及要分片的本地表和分片键。然后ClickHouse会自动将数据分布到集群中的各个节点。
示例:
sql
CREATE TABLE events_distributed
(
date Date,
event_id UInt32,
user_id UInt32,
...
) ENGINE = Distributed('my_cluster', 'my_database', 'events', event_id);
在这个例子中,数据将根据event_id
的值被均匀地分布到名为my_cluster
的集群中的各个节点。
总的来说,分区和分片都是用来管理大量数据的有效方式。分区可以帮助提高查询性能并简化数据管理,而分片可以提供更高的查询并发性并增加数据存储容量。
8.1. 什么是分区和分片
ClickHouse是一种面向列的数据库管理系统(DBMS),用于在线分析处理(OLAP)。
在ClickHouse中,我们也可以看到分区和分片的概念。
-
分区(Partitioning):
- 在ClickHouse中,分区是最大的数据组织单位。每个分区都包含表的一部分数据。你可以为每个月、每天或任何其他适合的时间段设置分区。
- ClickHouse允许按照自定义表达式(通常是日期或时间)进行表分区。这样可以优化数据处理和查询,以及进行数据清理操作,例如,你可以删除整个分区来删除旧的数据。
-
分片(Sharding):
- 分片在ClickHouse中是非常重要的概念。分片是为了在多台服务器上水平扩展ClickHouse集群,以增加处理能力和存储容量。
- 数据在分片之间分布。当执行查询时,查询将并行发送到所有分片,各个分片独立处理其上的数据,然后返回结果,由协调者结合这些结果并返回最终结果。
- 你可以配置任意数量的分片,每个分片可以有一个或多个副本。副本用于提供数据冗余和容错。
在ClickHouse中,分区和分片都是为了提供高效的数据处理和查询,以及高可用性和容错性。
8.2. 如何设置分区和分片
在ClickHouse中设置分区和分片需要在创建表时定义相应的参数。以下是如何设置分区和分片的详细说明和示例:
设置分区和分片主要涉及到PARTITION BY
子句和Distributed
引擎。首先,我们需要在创建表时设置分区键。然后,创建集群配置以及相应的本地表和分布式表,以实现数据分片。
- 设置分区:
分区是通过在CREATE TABLE
语句的PARTITION BY
子句中指定分区键来实现的。分区键可以是一个表达式,通常是日期或时间字段。
示例:创建一个按月分区的表。
sql
CREATE TABLE example_partitioned_table
(
event_time DateTime,
user_id Int32,
event_type String,
revenue Float64
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_time)
ORDER BY (user_id, event_time);
在这个例子中,我们创建了一个名为example_partitioned_table
的表,它包含四个字段:event_time
,user_id
,event_type
和revenue
。表使用MergeTree
引擎,并通过PARTITION BY toYYYYMM(event_time)
按月进行分区。
- 设置分片:
在设置分片时,我们需要首先创建一个集群配置,然后使用Distributed
引擎创建分布式表。以下是创建分片的步骤:
步骤1:创建集群配置
在config.xml
文件中,添加集群配置,如下所示:
xml
<remote_servers>
<example_cluster>
<shard>
<replica>
<host>example-host-01</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<host>example-host-02</host>
<port>9000</port>
</replica>
</shard>
</example_cluster>
</remote_servers>
在这个例子中,我们创建了一个包含两个分片的集群配置,名为example_cluster
。每个分片只有一个副本,对应于example-host-01
和example-host-02
。
步骤2:创建本地表
在每个分片上创建本地表。这个本地表结构与之前的例子相同,但增加了example_shard
后缀。
sql
CREATE TABLE example_local_table_example_shard
(
event_time DateTime,
user_id Int32,
event_type String,
revenue Float64
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_time)
ORDER BY (user_id, event_time);
步骤3:创建分布式表
在每个分片上创建分布式表,使用Distributed
引擎,并引用之前创建的集群配置和本地表。
sql
CREATE TABLE example_distributed_table
(
event_time DateTime,
user_id Int32,
event_type String,
revenue Float64
) ENGINE = Distributed(example_cluster, currentDatabase(), example_local_table_example_shard);
现在,我们可以将数据插入到example_distributed_table
中,数据会自动分布到不同的分片上。查询也会自动在所有分片上执行并汇总结果。
9. 使用索引
9.1. 什么是ClickHouse表索引
在数据库中,索引是一种数据结构,可以帮助快速查询、更新数据库表中的数据。索引可以根据定义所基于的表达式来创建,这个表达式通常是由一个或多个列的值组成的。在ClickHouse中,有两种主要的索引类型:主键索引和辅助索引。
-
主键索引:主键索引是在创建表时通过
ORDER BY
子句定义的。主键索引通常用于加速基于主键列的查询。当查询涉及到主键列时,ClickHouse将自动使用主键索引优化查询速度。主键索引要求行的键值唯一,这意味着在表中不能有具有相同键值的两行。 -
辅助索引:辅助索引是用于加速非主键列的查询操作。辅助索引需要使用特定的表引擎(如
MergeTree
系列引擎)并在该表引擎的参数中指定。与主键索引不同,辅助索引不要求行的键值唯一。辅助索引可以使用不同类型的索引,比如minmax
、set
、ngrambf_v1
等,这些索引类型对应不同的查询优化场景。
minmax(最小最大)索引:这种索引类型存储每个数据块的最小值和最大值。当进行范围查询时,若查询范围与数据块的最小最大值不相交,则可以跳过这个数据块,从而加速查询。minmax索引适用于范围查询优化,如WHERE子句中的BETWEEN、>、<等操作。
set(集合)索引:这种索引类型存储每个数据块的一个值集合。当查询某个特定值时,若该值不在数据块的值集合中,则可以跳过这个数据块。set索引适用于等值查询优化,如WHERE子句中的IN、=等操作。
ngrambf_v1(N-gram布隆过滤器)索引:这种索引类型使用布隆过滤器存储每个数据块的N-gram值。当查询包含子字符串的字符串时,若子字符串的N-gram值不在数据块的布隆过滤器中,则可以跳过这个数据块。ngrambf_v1索引适用于模糊字符串匹配查询优化,如WHERE子句中的LIKE、ILIKE等操作。
9.2. 如何创建和使用索引:
在ClickHouse中,创建索引需要在定义表的时候指定。主键索引是通过ORDER BY
子句在CREATE TABLE
语句中定义的。辅助索引则需要使用特定的表引擎(如MergeTree
系列引擎)并在该表引擎的参数中指定。
以下是创建和使用索引的示例:
- 创建主键索引:
sql
CREATE TABLE example_table
(
event_date Date,
event_id Int32,
revenue Float64
) ENGINE = MergeTree()
ORDER BY (event_date, event_id);
在这个例子中,我们创建了一个名为example_table
的表,它有三个字段:event_date
,event_id
和revenue
。然后,我们通过ORDER BY (event_date, event_id)
定义了一个主键索引,基于event_date
和event_id
两个列。
- 创建辅助索引:
sql
CREATE TABLE example_table
(
event_date Date,
event_id Int32,
revenue Float64,
INDEX revenue_index revenue TYPE minmax GRANULARITY 1
) ENGINE = MergeTree()
ORDER BY (event_date, event_id);
在这个例子中,我们在前一个例子的基础上增加了一个辅助索引revenue_index
。这个索引基于revenue
列,索引类型是minmax
,粒度是1。
使用索引:
在执行查询时,ClickHouse会自动使用索引,以加速数据查询。例如,以下查询会利用前面定义的主键索引:
sql
SELECT *
FROM example_table
WHERE event_date >= '2020-01-01'
AND event_id = 123;
在这个查询中,ClickHouse会利用主键索引,首先通过event_date
快速找到满足条件的数据部分,然后在这个范围内通过event_id
找到满足条件的数据行。
2. ClickHouse 表结构优化
在ClickHouse中,通过设计合理的表结构可以对数据查询进行优化。以下是一些常见的优化方法:
1. 数据去重
在创建表的时候,可以选择使用ReplacingMergeTree或CollapsingMergeTree引擎,它们可以自动进行数据去重。这在有大量重复数据,或者需要统计唯一值的场景下,可以大大提高查询效率。
使用ReplacingMergeTree引擎
sql
CREATE TABLE example_replacing (
id UInt32,
name String,
age UInt32,
created_at DateTime
) ENGINE = ReplacingMergeTree()
ORDER BY (id)
这个示例使用了ReplacingMergeTree引擎,它会根据排序键(id)对数据进行去重。
2. 数据排序
在创建表的时候,可以通过ORDER BY子句指定数据的排序键。ClickHouse会根据排序键对数据进行预排序,这样在处理范围查询或排序查询时,可以更快地获取到结果。
:通过ORDER BY子句指定数据的排序键。
sql
CREATE TABLE example_sorting (
id UInt32,
name String,
age UInt32,
created_at DateTime
) ENGINE = MergeTree()
ORDER BY (created_at, id)
这个示例根据created_at和id对数据进行排序。在进行范围查询或排序查询时,可以更快地获取结果。
3. 数据抽样
在创建表的时候,可以通过SAMPLE BY子句指定数据的抽样键。ClickHouse会根据抽样键对数据进行抽样存储,这样在处理大规模数据的统计查询时,可以通过抽样查询来快速获取近似结果。
:通过SAMPLE BY子句指定数据的抽样键。
sql
CREATE TABLE example_sampling (
id UInt32,
name String,
age UInt32,
created_at DateTime,
sampling_key UInt32
) ENGINE = MergeTree()
ORDER BY (created_at, id)
SAMPLE BY sampling_key
这个示例使用了sampling_key作为抽样键。在处理大规模数据的统计查询时,可以通过抽样查询来快速获取近似结果。
例如,要查询某个时间段内的平均年龄,可以使用带有SAMPLE子句的抽样查询:
sql
SELECT avg(age)
FROM example_sampling
WHERE created_at >= '2021-01-01' AND created_at < '2021-02-01'
SAMPLE 0.1
这个查询只会处理大约10%的数据,但可以在短时间内获得近似的结果。