【基础篇】ClickHouse 表结构设计

文章目录

  • [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 有一些特殊之处,包括在创建表时:

  1. 表引擎:在创建表的语句中,需要指定表引擎。这是 ClickHouse 的一项独特功能,表引擎决定了数据的存储方式和可用的查询处理。在标准 SQL 中,通常不需要指定表引擎。

  2. 排序顺序:在创建表的语句中,可以指定排序键,它决定了数据在磁盘上的排序顺序。在标准 SQL 中,数据的物理排序通常是不透明的。

  3. 数据类型:ClickHouse 支持一些标准 SQL 中没有的数据类型,例如 ArrayTupleMapUUID等。

  4. 主键和索引:与标准 SQL 不同,ClickHouse 不强调主键的概念,实际上,主键在 ClickHouse 中主要用于数据分区和执行数据采样查询。此外,ClickHouse 支持更灵活和强大的索引类型。

  5. 分区: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家族的主要成员及其使用场景:

  1. 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中也有所应用。

  1. 分区 (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);
  1. 分片 (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中,我们也可以看到分区和分片的概念。

  1. 分区(Partitioning):

    • 在ClickHouse中,分区是最大的数据组织单位。每个分区都包含表的一部分数据。你可以为每个月、每天或任何其他适合的时间段设置分区。
    • ClickHouse允许按照自定义表达式(通常是日期或时间)进行表分区。这样可以优化数据处理和查询,以及进行数据清理操作,例如,你可以删除整个分区来删除旧的数据。
  2. 分片(Sharding):

    • 分片在ClickHouse中是非常重要的概念。分片是为了在多台服务器上水平扩展ClickHouse集群,以增加处理能力和存储容量。
    • 数据在分片之间分布。当执行查询时,查询将并行发送到所有分片,各个分片独立处理其上的数据,然后返回结果,由协调者结合这些结果并返回最终结果。
    • 你可以配置任意数量的分片,每个分片可以有一个或多个副本。副本用于提供数据冗余和容错。

在ClickHouse中,分区和分片都是为了提供高效的数据处理和查询,以及高可用性和容错性。

8.2. 如何设置分区和分片

在ClickHouse中设置分区和分片需要在创建表时定义相应的参数。以下是如何设置分区和分片的详细说明和示例:

设置分区和分片主要涉及到PARTITION BY子句和Distributed引擎。首先,我们需要在创建表时设置分区键。然后,创建集群配置以及相应的本地表和分布式表,以实现数据分片。

  1. 设置分区:
    分区是通过在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_timeuser_idevent_typerevenue。表使用MergeTree引擎,并通过PARTITION BY toYYYYMM(event_time)按月进行分区。

  1. 设置分片:
    在设置分片时,我们需要首先创建一个集群配置,然后使用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-01example-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中,有两种主要的索引类型:主键索引和辅助索引。

  1. 主键索引:主键索引是在创建表时通过ORDER BY子句定义的。主键索引通常用于加速基于主键列的查询。当查询涉及到主键列时,ClickHouse将自动使用主键索引优化查询速度。主键索引要求行的键值唯一,这意味着在表中不能有具有相同键值的两行。

  2. 辅助索引:辅助索引是用于加速非主键列的查询操作。辅助索引需要使用特定的表引擎(如MergeTree系列引擎)并在该表引擎的参数中指定。与主键索引不同,辅助索引不要求行的键值唯一。辅助索引可以使用不同类型的索引,比如minmaxsetngrambf_v1等,这些索引类型对应不同的查询优化场景。

  1. minmax(最小最大)索引:这种索引类型存储每个数据块的最小值和最大值。当进行范围查询时,若查询范围与数据块的最小最大值不相交,则可以跳过这个数据块,从而加速查询。minmax索引适用于范围查询优化,如WHERE子句中的BETWEEN、>、<等操作。

  2. set(集合)索引:这种索引类型存储每个数据块的一个值集合。当查询某个特定值时,若该值不在数据块的值集合中,则可以跳过这个数据块。set索引适用于等值查询优化,如WHERE子句中的IN、=等操作。

  3. ngrambf_v1(N-gram布隆过滤器)索引:这种索引类型使用布隆过滤器存储每个数据块的N-gram值。当查询包含子字符串的字符串时,若子字符串的N-gram值不在数据块的布隆过滤器中,则可以跳过这个数据块。ngrambf_v1索引适用于模糊字符串匹配查询优化,如WHERE子句中的LIKE、ILIKE等操作。

9.2. 如何创建和使用索引:

在ClickHouse中,创建索引需要在定义表的时候指定。主键索引是通过ORDER BY子句在CREATE TABLE语句中定义的。辅助索引则需要使用特定的表引擎(如MergeTree系列引擎)并在该表引擎的参数中指定。

以下是创建和使用索引的示例:

  1. 创建主键索引:
sql 复制代码
CREATE TABLE example_table
(
    event_date Date,
    event_id Int32,
    revenue Float64
) ENGINE = MergeTree()
ORDER BY (event_date, event_id);

在这个例子中,我们创建了一个名为example_table的表,它有三个字段:event_dateevent_idrevenue。然后,我们通过ORDER BY (event_date, event_id)定义了一个主键索引,基于event_dateevent_id两个列。

  1. 创建辅助索引:
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%的数据,但可以在短时间内获得近似的结果。

相关推荐
RestCloud23 分钟前
为什么说零代码 ETL 是未来趋势?
数据库·api
浮游本尊1 小时前
Java学习第22天 - 云原生与容器化
java
ClouGence2 小时前
CloudCanal + Paimon + SelectDB 从 0 到 1 构建实时湖仓
数据库
渣哥3 小时前
原来 Java 里线程安全集合有这么多种
java
间彧3 小时前
Spring Boot集成Spring Security完整指南
java
间彧3 小时前
Spring Secutiy基本原理及工作流程
java
Java水解4 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆6 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学7 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole7 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端