【基础篇】ClickHouse 表结构设计


在这里插入图片描述

1. ClickHouse 表结构设计

1. 表的创建

在ClickHouse中,创建表的基本语法如下:

CREATE TABLE table_name (
    column1 datatype,
    column2 datatype,
    ...
) ENGINE = engine

其中:

  • table_name 是要创建的表的名称。
  • column1, column2, ... 是表的列的名称,datatype 是各列的数据类型。
  • ENGINE 是表引擎的名称。在ClickHouse中,表引擎决定了数据的存储和索引方式。

例如,以下是一个创建名为users的表的示例,该表有id(整数类型,主键),name(字符串类型),age(整数类型)和country(字符串类型)的列:

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语句:

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语句:

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语句:

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的主要表引擎,支持索引和数据分区,适用于大数据计算。

使用场景:适用于大数据分析,如用户行为分析、日志分析等。

示例:

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表引擎用于存储日志和其他机器数据。不支持索引和数据分区。

使用场景:适用于小数据量的日志和其他机器数据的存储。

示例:

CREATE TABLE example_log
(
    event_time DateTime,
    event_type String,
    event_data String
) ENGINE = Log;

3. Memory:

说明:Memory表引擎将所有数据存储在RAM中,适用于临时表和小数据量。

使用场景:适用于需要快速访问和计算的小数据量场景。

示例:

CREATE TABLE example_memory
(
    key UInt32,
    value String
) ENGINE = Memory;

4. Distributed:

说明:Distributed表引擎用于在多个节点间分布查询和数据。它自动分发查询和数据到所有节点。

使用场景:适用于需要在多个节点间进行数据分析的分布式场景。

示例:

CREATE TABLE example_distributed
(
    date Date,
    id UInt32,
    value String
) ENGINE = Distributed('my_cluster', 'my_database', 'example_merge_tree', rand());

5. Kafka:

说明:Kafka表引擎用于和Kafka集成,可用于实时数据流处理。

使用场景:适用于实时数据处理,如日志实时处理、实时数据分析等。

示例:

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引擎用于预处理数据,可以提高查询性能。

使用场景:适用于需要对大数据进行预处理以提高查询性能的场景。

示例:

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操作、数据导入导出等。

示例:

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的基本表引擎,支持索引和数据分区。

使用场景:适用于大数据分析,如用户行为分析、日志分析等。

示例:

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用于实时删除重复数据。当合并过程中发现相同的主键数据时,只保留最新的一条记录。

使用场景:适用于需要实时删除重复数据的场景,如实时去重、数据清洗等。

示例:

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用于实时对数值型字段进行求和。在合并过程中,具有相同主键的记录将被合并为一条记录,并对指定字段求和。

使用场景:适用于需要对数值型字段进行实时求和的场景,如计数器、流量统计等。

示例:

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用于实时对数据进行聚合。在合并过程中,具有相同主键的记录将被聚合为一条记录,根据指定的聚合函数进行计算。

使用场景:适用于需要实时聚合数据的场景,如统计、报表等。

示例:

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表示删除)。在合并过程中,符号相反且其他列相同的记录会被抵消。

使用场景:适用于需要实时删除重复数据的场景,如数据同步、状态更新等。

示例:

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的列来表示记录的版本。在合并过程中,版本较新的记录会覆盖版本较旧的记录。

使用场景:适用于需要实时删除重复数据并支持版本控制的场景,如数据历史记录、状态更新等。

示例:

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是一种非常简单的引擎,它将所有列保存在一个文件中。不支持索引,所以查询速度较慢,但是插入速度快。

使用场景:适用于小型数据集和日志记录。

示例:

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是一种简单的引擎,它把每一列的数据分别存储在不同的文件中。不支持索引,适用于大量的日志数据。

使用场景:适合大量的日志记录和流数据。

示例:

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引擎将所有数据存储在内存中。它支持实时查询,并且具有极高的查询速度。但是,由于它将所有数据保存在内存中,因此在服务器重启或崩溃时,数据会丢失。

使用场景:适用于需要快速查询的小型数据集,如缓存、临时表或实时分析。

示例:

CREATE TABLE example_memory
(
    date Date,
    id UInt32,
    value String
) ENGINE = Memory;

5.1.2. File:

说明:File引擎将数据保存在服务器的文件系统中。它支持将数据存储为各种文件格式(如CSV、Parquet、JSON等)。File引擎不支持索引,因此查询速度较慢。

使用场景:适用于需要将数据以特定文件格式存储的场景,如ETL操作、数据备份或离线分析。

示例:

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引擎主要用于调试或测试,例如,你可能想要测试插入或查询的性能,而不实际保存任何数据。另一个常见用例是作为一个"黑洞"表,用来快速丢弃不需要的数据。

示例:

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表引擎非常有用。

示例:

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表引擎非常有用。

示例:

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表引擎非常有用。

示例:

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子句定义分区键。例如,如果你有一个包含用户活动记录的表,你可能希望根据时间将数据分区,这样就可以轻松地删除旧的数据。

示例:

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会自动将数据分布到集群中的各个节点。

示例:

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子句中指定分区键来实现的。分区键可以是一个表达式,通常是日期或时间字段。

示例:创建一个按月分区的表。

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文件中,添加集群配置,如下所示:

<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后缀。

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引擎,并引用之前创建的集群配置和本地表。

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. 创建主键索引:
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. 创建辅助索引:
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会自动使用索引,以加速数据查询。例如,以下查询会利用前面定义的主键索引:

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引擎

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子句指定数据的排序键。

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子句指定数据的抽样键。

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子句的抽样查询:

SELECT avg(age)
FROM example_sampling
WHERE created_at >= '2021-01-01' AND created_at < '2021-02-01'
SAMPLE 0.1

这个查询只会处理大约10%的数据,但可以在短时间内获得近似的结果。

猜你喜欢

转载自blog.csdn.net/wangshuai6707/article/details/132921055