刚开始接触ClickHouse?12个最容易犯的错误以及避坑方法

clickhouse 连接外部数据源(Mysql Kafka) clickhouse连接mysql数据源 在linux123上建立好测试的数据库和表并插入数据 create database bigdataClickHouse; use bigdataClickHouse; create table student( id int, name varchar(40), age int); insert into student values(3,'jack',12); insert into student values(4,'jac 阅读详情
AI摘要

本文指出ClickHouse新手用户因配置错误或误解功能,常遇到12个问题,如Too many parts、过早水平扩展等。针对每个问题,推荐了解决方案或正确使用方法,还提醒避免在生产环境依赖实验性功能,可尝试在云上使用ClickHouse。

本文字数:11600;估计阅读时间:28 分钟

审校:庄晓东(魏庄)

引言

在ClickHouse,我们始终在思考我们的入门体验以及如何帮助用户在尽可能短的时间内从我们的产品中获得价值。虽然大多数用户都有一个流畅的上手经验,但我们意识到ClickHouse是一个复杂的软件,并且引入了很多新的概念。加上大规模管理ClickHouse的挑战,这也是我们开发serverless ClickHouse解决方案的原因之一,它能自动处理许多常见的入门问题和后续扩展方面的挑战。

然而,有些问题仅仅是由于配置错误或更常见的是对ClickHouse行为和功能的误解。在这篇文章中,我们突出了新手用户遇到的最常见的12个问题,这些问题是由于在使用ClickHouse的过程中,不遵循最佳实践,甚至反最佳实践而导致的。对于每一个问题,我们都推荐了一个解决方案或正确的使用方法。

1. Too many parts

这是一个常见的ClickHouse错误,通常是不正确的使用方式和不遵循最佳实践导致。当插入数据时,用户经常会遇到这个错误,并且这个错误会出现在ClickHouse的日志中或作为一个INSERT请求的响应返回给客户端。为了理解这个错误,用户需要对ClickHouse中的part概念有一个基本的了解。

ClickHouse中的表,是由主键排序后的data parts组成(默认情况下,在创建表时按ORDER BY子句排序)。当数据被插入到一个表中时,会创建单独的part,每个part都按主键的字典顺序排序。例如,如果主键是 (CounterID, Date) ,则part中的数据首先按 CounterID 排序,然后在每个 CounterID 值内按 Date 排序。在后台,ClickHouse合并(merge) data part以实现更高效的存储,类似于Log-structured merge tree。每个part都有自己的primary索引,以实现高效地扫描和定位数据在parts中的位置。当parts合并时,primary索引也会合并。

随着parts的数量增加,由于需要扫描更多的索引和读取更多的文件,查询不可避免地会变慢。在part数量较多的情况下,用户也可能有启动时间较慢的体感。创建过多的parts会导致需要进行更多的内部合并,以此来保持较低数量的parts和高性能的查询。虽然合并是并发执行的,但在滥用或配置错误的情况下,parts的数量可能会超过参数配置的限制(parts_to_throw_insert和max_parts_in_total)。虽然这些限制可以进行调整,但会牺牲查询性能,这更多地指向了您的使用方式存在的问题。随着查询性能的降低,大量的pars还可能给ClickHouse Keeper带来更大的压力。

那么,为何会有太多这样的parts呢?

选择不当的分区键

一个常见的原因是使用有过多基数(cardinality)的分区键。在创建表时,用户可以指定一个列作为分区键,按该键来分隔数据。每一个键值都会创建一个新的文件目录。这通常是一个数据管理技巧,允许用户在表中地逻辑分隔数据,例如按天。如DROP PARTITION这样的操作允许快速删除数据子集。然而,这个功能很容易被误用,用户将其理解为一个简单的查询优化技巧。更重要的是,属于不同分区的parts永远不会被合并。如果选择一个高基数的键,例如 date_time_ms ,作为分区键,那么分散在成千上万个文件夹中的parts永远不会是合并的候选对象 - 直到超过预配置的限制,并在后续的插入中引发"Too many inactive parts (N). Parts cleaning are processing significantly slower than inserts"错误。解决这个问题很简单:选择一个基数 < 1000 的合理分区键。

许多小的插入

除了分区键选择不恰当以外,这个问题也可能是由于许多小的插入所造成的。每次向ClickHouse中插入数据都会导致一个插入块被转换为一个part。为了保持parts的数量在可管理的范围内,用户应该在客户端缓存数据并批量插入数据 - 理想情况下,至少1000行。如果客户端无法缓存,用户可以将这个任务推给ClickHouse通过异步插入实现。在这种情况下,ClickHouse将在本地缓存插入的数据,随后再插入到底层表中。

buffer表在这里也是一个选择,但在处理失败时的能力较差,因为它们会在内存中保持插入,直到发生刷新。相对于异步插入,buffer表有一些优势 - 主要是数据在缓冲区中时是可查询的,并且它们与物化视图的目标表的缓冲区兼容。

过多的物化视图

其他可能原因是过多的物化视图。物化视图实际上是当一个数据块被插入到一个表中时运行的触发器。它们通过例如GROUP BY来转换数据,然后将结果插入到另一个表中。这种技术经常被用来通过在INSERT时,预计算聚合值来加速某些查询。用户可以创建这些物化视图,但可能导致过多的parts。一般来说,我们建议用户在创建视图时要注意开销,并尽可能整合它们。

此外,mutation(如下面所讨论的)也可能引起合并的压力和parts的积累。最后,我们应该注意,这个错误虽然是最常见的,但只是上述误配置的一个表现。例如,由于分区键选择不当,用户可能会遇到其他问题。这些包括但不限于“no free inodes on the filesystem”、备份时间过长、以及在复制上的延迟等(以及ClickHouse Keeper上的高负载)。

2. 过早地进行水平扩展

我们经常收到有自建的新用户向我们咨询关于编排和如何扩展到几十个、甚至上百个节点的建议。虽然像Kubernetes这样的技术使得部署多个无状态应用的实例变得相对简单,但在几乎所有情况下,ClickHouse都不应该需要这种模式。与其他可能由于固有限制(例如,JVM堆大小)而受到机器大小限制的数据库不同,ClickHouse从一开始就被设计成利用机器的全部资源。在拥有数百核、数TB的RAM和数PB的磁盘空间的服务器上成功部署了ClickHouse的案例经常可以看到。大多数分析查询都有排序、过滤和聚合阶段。这些都可以独立地并发进行,并且默认情况下,会使用与核数相同的线程数,从而为查询利用整台机器的资源。

首先垂直扩展有很多好处,主要是成本效率、更低的操作成本,以及最小化网络数据的传输开销,从而有更好的查询性能。当然,用户需要额外做冗余,在大多数场景中,两台机器应该足够了。

总之,先垂直再水平!

3. mutation之痛

虽然在OLAP用例中很少见,但有时修改数据是不可避免的。为了满足这一需求,ClickHouse提供了mutation功能,允许用户通过ALTER修改已插入的数据。ClickHouse在不需要做数据变更的场景下表现最佳,任何需要在插入后更新数据的场景都值得讨论。

在内部,mutation是通过重写整个data parts来完成的。这个过程跟合并公用相同的线程池。还要注意,默认情况下,mutation需要应用在所有副本上。因此,mutation既是CPU密集型的,也是IO密集型的,应该谨慎地执行,并限制给管理员运行。由于mutation导致的资源压力会以多种方式表现出来。典型的是,正常计划的合并会堆积,进而导致我们前面提到的“Too many parts”问题。此外,用户可能会经历复制延迟。system.mutations表提供给管理员目前正在执行的的mutation的一些指示。注意,mutation可以被取消,但不能回滚,使用KILL MUTATION取消正在执行的mutation。

去重

我们经常看到用户因为有重复的数据而需要执行合并。我们通常建议用户在插入到ClickHouse之前的上游解决这个问题。如果这样做不可行,用户有几个选择:在查询时去重或使用ReplacingMergeTree。

在查询时去重可以通过对唯一字段的行进行group by,并使用argMax函数和日期字段来确定其他字段的最新值。ReplacingMergeTree允许具有相同排序键(ORDER BY键)的行在合并时去重。注意这只是“尽力”去完成:因为执行合并的线程不确定什么时间去执行,从而导致parts不会被合并。因此,它不能保证没有重复。用户还可以使用FINAL修饰符在 SELECT 时强制进行去重(再次谨慎使用,因为它是资源密集型的,尽管近期有所改进,但可能会很慢),或者通过OPTIMIZE FINAL在磁盘上强制合并。

在需要从ClickHouse中删除数据的情况下,用户也可以使用lightweight deletes代替mutation。这采用DELETE语句的形式,该语句接受WHERE子句来过滤行。这只是将行标记为已删除。这些标记将在查询时用于过滤行,并在parts合并时被删除。

注意:此功能处于实验阶段,需要设置 SET allow_experimental_lightweight_delete = true; 。在大多数情况下,它比使用mutation更有效率,除非你正在进行大规模的批量删除。

4. 不必要地使用复杂类型

除了支持常用的原始类型外,ClickHouse还为Nested、Tuple、Map甚至JSON等复杂类型提供了丰富的支持。有时,这是格式化数据的唯一方式,所以有充分的理由支持这些类型,但我们建议尽可能使用原始类型,因为它们提供了最佳的插入和查询性能。

例如,我们最近看到用户热衷于利用在ClickHouse 22.4中添加的JSON功能。这个强大的功能允许表结构从数据动态推断出来,避免了用户手动指定字段类型。但请谨慎使用这一功能,不要用它来替代显示指定列类型。因为这个功能有用户该知道的一些限制:

  • 插入时的增加成本,因为需要动态创建列

  • 没有使用最优的类型,比如不必要的使用Nullable。

  • 无法在主键中使用JSON列

其中的最后两个无疑导致了更差的压缩和查询/插入性能。与其让他指定所有列的类型,不如为选择性地使用这种特定类型,例如Kubernetes标签,因为数据可能会发生变化。总之,如果你知道你的表结构...请显式地指定它!

注意:JSON对象类型处于实验阶段,并正在进行改进。关于此功能仍在发展,并可能在后续版本中有所改变。

我们还经常看到用户使用Nullable类型。这能将Null值与类型的默认值区分开来。这可能很有用,但需要一个额外的Uint8列来确定哪些值为空。这会导致每个值需要额外一个字节的存储(尽管压缩性上较好),并增加查询时间开销。只有在真正需要它的时候才使用Nullable!

5. 插入时的去重

新用户经常对ClickHouse的去重策略感到惊讶。当出现相同的插入似乎没有任何效果时,这种情况通常会发生。例如,考虑以下内容:

CREATE TABLE temp
(
   `timestamp` DateTime,
   `value` UInt64
)
ENGINE = MergeTree
ORDER BY tuple()
 
INSERT INTO temp VALUES ('2022-10-21', 10), ('2022-10-22', 20), ('2022-10-23', 15), ('2022-10-24', 18)
INSERT INTO temp VALUES ('2022-10-21', 10), ('2022-10-22', 20), ('2022-10-23', 15), ('2022-10-24', 18)
 
clickhouse-cloud :) SELECT * FROM temp
 
SELECT *
FROM temp
 
┌───────────timestamp─┬─value─┐
│ 2022-10-21 00:00:00 │    10 │
│ 2022-10-22 00:00:00 │    20 │
│ 2022-10-23 00:00:00 │    15 │
│ 2022-10-24 00:00:00 │    18 │
└─────────────────────┴───────┘

新用户可能会对这里的结果感到惊讶,尤其是如果他们之前的经验是在ClickHouse的单个本地实例上。这种行为是由 replicated_deduplication_window 设置造成的。

当数据插入ClickHouse时,它会创建一个或多个块(parts)。在复制的环境中,ClickHouse Keeper中也会写入一个哈希值。随后插入的块会与这些哈希值进行比较,并在发现匹配时被忽略。这很有用,因为它允许客户端在没有从ClickHouse获得确认的情况下安全地重试插入,例如,由于网络中断。这要求块是完全相同的,即大小相同、顺序相同的行。这些哈希值仅存储最近的100个块,尽管这可以修改。注意,设置更高的值会由于需要跟更多的哈希值比较而减慢插入。

对于非复制实例,可以通过 non_replicated_deduplication_window 设置启用此相同行为。在这种情况下,哈希值存储在本地磁盘上。

6. 选择不当的主键

初次使用ClickHouse的用户经常很难完全理解其独特的主键概念。与基于B(+)Tree的OLTP数据库不同,后者针对快速定位特定行进行了优化,ClickHouse使用了一个稀疏索引,该索引针对每秒插入的数百万行和PB级数据集进行了设计。与OLTP数据库相反,该索引依赖于磁盘上排序过的数据,以快速识别可能匹配查询的一组行 - 这是分析查询中的常见要求。索引实际上允许part文件在流入处理引擎之前快速的识别和匹配。

这种方法的有效性,对于查询性能和压缩而言,依赖于用户在创建表时通过ORDER BY子句选择好的主键列。通常,用户应选择他们经常用于过滤的列,一般不超过3列。这些列的顺序至关重要,可能会影响到压缩以及对第一列以外列的过滤性能。为了在查询中有效过滤次要列和高效的列文件压缩比,最佳的方法是按照它们的基数以升序排列主键中的列。

7. 过度使用跳数索引

当需要加速查询时,主键通常是用户首先考虑的手段。然而,表只限于一个主键,查询的方式可能会使其失效,即对于多种场景,无法有效利用主键的查询。在这些情况下,ClickHouse可能会被迫对每个列执行全表扫描,当应用WHERE子句条件时。通常这仍然足够快,但在某些情况下,用户会使用跳数索(data skipping index),希望轻松地加速这些查询。

跳数索引使用了特定的数据结构,允许ClickHouse跳过大量确保没有匹配值的数据块。更具体地说,它们在块颗粒上创建索引(实际上是标记),允许跳过不满足WHERE子句的块。

在某些情况下,可以加速特定的查询,但他们通常被过度使用,不是简单的创建而是需要仔细设计才能发挥最大作用。因此,我们经常看到它们使表设计复杂化,并减慢插入性能,而很少(如果有的话)提高查询性能。我们总是鼓励用户阅读概念和最佳实践。

通常,只有在没有其他选择的情况下才应考虑跳数索引 - 具体来说,只有在研究其他选择之后,才应使用这种高级功能,例如修改主键(请参阅创建额外主索引的选项),使用投影(projections)或物化视图。通常,只有在主键和目标非主列/表达式之间存在强相关性时,才考虑跳过索引。如果没有任何实际的关联,跳数索引将匹配大多数块 - 结果所有颗粒都被读入内存并评估。在这种情况下,已经有了索引开销,但没有任何好处,实际上减慢了整个表的扫描。

8. LIMIT并不总是立即停止 + 点查

我们经常发现习惯于OLTP的用户在初次接触ClickHouse时,试图使用LIMIT子句通过限制返回的结果数量来优化查询。从OLTP数据库的角度来看,这种方式应该直观地优化查询:返回的数据越少 = 结果越快,对吗?答案是既对又错。

这种技巧的有效性取决于查询是否可以完全以流方式运行。例如,像 SELECT * FROM table LIMIT 10 这样的查询在查到10行结果并将结果返回给用户之前,只会扫描前几parts的几个粒度(granules)。由于 optimize_in_read_order 设置默认为1,所以当用户按主键字段对SELECT进行排序时,这也是成立的。但是,如果用户运行 SELECT a from table ORDER BY b LIMIT N ,其中表是按a而不是b排序的,ClickHouse不能避免读取整个表,即查询无法提前终止。

对于聚合,情况稍微复杂一些。除非用户按主键分组并设置 optimize_aggregation_in_order=1 ,否则也需要进行全表扫描。在这种情况下,一旦获得足够的结果,就会发送一个传播信号。只要查询的前几步能够流式传输数据,例如过滤器,这个机制就会起作用,查询会提前终止。但通常,聚合在返回和应用LIMIT作为最后阶段之前必须读取所有表数据。

举个例子,我们从UK Property Price Paid教程中创建并加载了一个包含2755万行的表。这个数据集在我们的play.clickhouse.com环境中是可用的。

对于 optimize_aggregation_in_order=0 ,这个聚合查询按主键分组,在应用LIMIT 1子句之前执行了全表扫描:

clickhouse-cloud :) SELECT
    postcode1, postcode2,
    formatReadableQuantity(avg(price)) AS avg_price
FROM uk_price_paid
GROUP BY postcode1, postcode2
LIMIT 1;

┌─postcode1─┬─postcode2─┬─avg_price───────┐
│ AL4       │ 0DE       │ 335.39 thousand │
└───────────┴───────────┴─────────────────┘
 
Elapsed: 3.028 sec, read 27.55 million rows, 209.01 MB.

而对于 optimize_aggregation_in_order=1 ,查询能够快速地处理并因此处理更少的数据:

clickhouse-cloud :) SELECT
       postcode1, postcode2,
       formatReadableQuantity(avg(price))  AS avg_price
FROM uk_price_paid
GROUP BY postcode1, postcode2
LIMIT 1
SETTINGS optimize_aggregation_in_order = 1;
 
┌─postcode1─┬─postcode2─┬─avg_price───────┐
│ AL4       │ 0DE       │ 335.39 thousand │
└───────────┴───────────┴─────────────────┘
 
Elapsed: 0.999 sec, read 4.81 million rows, 36.48 MB.

我们还经常看到即使是经验丰富的用户也会在多分片环境中被LIMIT的不太明确的行为所困扰,这样的环境中,一个表可以有很多分片。分片允许用户将其数据分割或复制到多个ClickHouse实例中。当一个带有LIMIT N子句的查询发送到一个分片表时,例如一个分布式表,这个子句将被传递到每个分片。每个分片都需要收集前N个结果,并返回给协调节点。当用户运行需要全表扫描的查询时,这可能会特别消耗资源。这类查询通常是“点查”,查询的目标只是定位几行数据。虽然这在ClickHouse中可以通过良好的索引设计来实现,但一个未优化的版本,再加上一个LIMIT子句,可能会非常消耗资源。

9. Readonly tables

在复制环境中,当一个节点失去与ZooKeeper的连接时,这种情况就会发生。这通常总是由于ZooKeeper的问题造成的。尽管ClickHouse Keeper的发布解决了与ZooKeeper相关的许多挑战,但如果该组件资源不足,这个问题仍然可能出现。常见的原因是在生产环境中将keeper与ClickHouse部署在相同的主机上,或ZooKeeper JVM资源配置不佳。通常,通过确保此组件部署在单独的硬件上,并给予充足的资源可以解决此问题。

10. 查询内存限制超出

对于新用户来说,ClickHouse经常像魔术一样 - 每个查询都非常快速,即使是大数据集的查询。然而,实际的使用情况会测试到ClickHouse的极限。超出内存的查询可能是由多种原因造成的。我们最常见的是在高基数字段上执行大型连接或聚合。如果性能至关重要,而这些查询是必需的,我们经常建议用户进行扩展,云上实例可以毫不费力完成。然而,我们理解,在自建的场景下,这有时并不简单,也许甚至不需要最佳性能。在这种情况下,用户有一些选择。

聚合

对于内存密集型的聚合或排序场景,用户可以使用设置max_bytes_before_external_group_by 和 max_bytes_before_external_sort 。简而言之,这确保任何聚合在超出内存阈值时都可以“溢出”到磁盘。这无疑会影响查询性能,但将有助于确保查询不会OOM。后者的排序参数帮助解决与内存密集型排序相似的问题。在分布式环境中,这尤其重要,因为协调节点从其他分片接收排序后的响应。在这种情况下,可以要求协调服务器对一个大于其可用内存的数据集进行排序。有了 max_bytes_before_external_sort ,排序可以溢出到磁盘。这种设置对于用户在 GROUP BY 后有一个 ORDER BY ,并带有 LIMIT 的情况也有用,特别是在查询是分布式的情况下。

Join

对于Join,用户可以选择不同的Join算法,这可以帮助减少所需的内存。默认情况下会使用Hash Join,这提供最完整的功能,并且经常能提供最佳性能。此算法将Join的右表加载到内存中的哈希表中,然后对左表进行评估。为了最小化内存,用户因此应将较小的表放在右侧。然而,这种方法在内存有限的情况下仍然有限制。在这些情况下,可以通过 join_algorithm 设置启用 partial_merge 连接。这是sort-merge算法的变种,首先将右表排序到块里,并为它们创建一个min-max索引。然后,它按连接键对左表的parts进行排序。使用min-max索引来跳过不需要的右表块。这在损失一定性能的情况下减少了内存使用。进一步延伸这个概念, full_sorting_merge 算法允许在右表非常大,不适合在内存查找的情况下执行Join,例如复杂的子查询。在这种情况下,如果两侧都不适合内存,那么它们都会先在磁盘上进行排序,从而允许大表Join。

自20.3起,ClickHouse支持 join_algorithm 设置为auto。这指示ClickHouse自适应选择Join方法,其中优先使用Hash-Join算法,直到内存限制为止,再尝试partial_merge算法。最后,关于Join,我们鼓励读者关注分布式Join的行为以及如何最大限度地减少它们的内存消耗。

流氓查询

其他导致内存问题的原因是没有对用户做限制。在这些情况下,我们看到用户在没有quotas或查询复杂性限制(各种_overflow_mode参数)的情况下发起流氓查询。如果ClickHouse实例的用户比较多,并且水平参差不齐,这些控制手段对于提供一个稳健的服务是必不可少的。

ClickHouse还最近引入了新的内存overcommit功能。之前,查询受到 max_memory_usage 设置(默认10GB)的限制,这提供了一个简单粗暴的限制。用户可以在单个查询上提高内存,但可能会影响其他用户使用。内存overcommit允许运行更多内存密集型的查询,只要存在足够的资源。当达到最大服务器内存限制(max_server_memory_usage)时,ClickHouse将确定哪些查询最超配,并尝试杀死这些查询-并且可能不是触发内存超限的查询。如果不是,查询将等待一段时间,直到高内存查询被杀死,然后继续运行。这使得低内存消耗的查询始终可以运行,而高内存消耗的查询可以在服务空闲并且资源可用时运行。此行为可以在server和user级别进行调整。

11. 关于物化视图的问题

物化视图是ClickHouse的一个强大特性。通过允许在插入时重新定向和转换数据,用户可以优化特定查询。当需要多于一个主索引时,我们经常看到用户使用这种技巧。与物化视图相关的常见问题很多,可能足以写一篇单独的博客文章。简单归纳最常见的问题如下:

  • 我们经常看到用户对物化视图的工作方式存在误解。物化视图对源表数据一无所知,实际上只是在插入时的触发器 - 只能在插入的数据块上运行。它们无法看到合并、分区删除或mutation。如果用户更改了源表,他们因此也必须更新关联的物化视图 - 目前没有办法能保持它们同步。

  • 用户在单个表上添加了太多的物化视图。这些视图并不是没有消耗的,并且必须在每次插入时运行。一个表上超过50个物化视图通常是过多的,会降低插入速度。除了计算开销外,每个物化视图都会从其运行的块创建一个新的part - 可能引发前面讨论的“Too many Parts”问题。请注意,通过设置 parallel_view_processing 来并行运行视图,可以提高性能。

  • 状态函数是ClickHouse的一个引人注目的功能,允许数据在后续的查询中使用聚合函数进行总结。具有许多这些函数的物化视图,尤其是计算分位数状态函数的那些物化视图,可能对CPU开销很大并导致插入变慢。

  • 我们经常看到物化视图的列和目标Aggregating/SummingMergeTree表上的列不匹配。目标表的ORDER BY子句必须与物化视图中的SELECT子句的GROUP BY一致。如果这两者不同,您会发现那些不一致列上的数据会被损坏。以下是正确的示例:

CREATE MATERIALIZED VIEW test.basic
ENGINE = AggregatingMergeTree() PARTITION BY toYYYYMM(StartDate) ORDER BY (CounterID, StartDate)
AS SELECT
   CounterID,
   StartDate,
   sumState(Sign)    AS Visits,
   uniqState(UserID) AS Users
FROM test.visits
GROUP BY CounterID, StartDate;
CREATE MATERIALIZED VIEW test.summing_basic
ENGINE = SummingMergeTree
PARTITION BY toYYYYMM(d)
ORDER BY (CounterID, StartDate)
AS SELECT CounterID, StartDate, count() AS cnt
FROM source
GROUP BY CounterID, StartDate;
  • 与上述类似,物化视图的SELECT的列名必须与目标表匹配 - 不要依赖于列的顺序。使用别名确保它们匹配。请注意,目标表可以有默认值,因此视图的列可以是目标表的子集。以下是一个正确的示例 - 请注意,需求将 count()别名为counter :

CREATE MATERIALIZED VIEW
test.mv1 (timestamp Date, id Int64, counter Int64)
ENGINE = SummingMergeTree
ORDER BY (timestamp, id)
AS
SELECT timestamp, id, count() as counter
FROM source
GROUP BY timestamp, id;

12. 生产环境中的实验性功能

在ClickHouse,我们定期发布新功能。在某些情况下,新功能被标记为"experimental",这意味着它们将从现实场景的使用和社区的反馈中受益。最终,这些功能会发展到被视为“production ready”的程度,或者如果发现它们通常不是很有用或有其他方法来实现最初的目标,则会被抛弃。虽然我们鼓励用户尝试实验性功能,但我们建议不要在生产环境中严重依赖它们。

我们在文档中将所有实验性功能做了标记,并且任何使用都需要用户设置一个参数来启用特定的实验性功能,例如: SET allow_experimental_lightweight_delete = true 。

结论

如果你读到这里,你应该已经准备好在生产环境中管理ClickHouse集群 - 或者至少能够避免许多常见的问题!管理拥有数PB级数据的ClickHouse集群无疑是具有挑战性的,即使对于最有经验的使用者也是如此。为了避免这些挑战并仍然体验ClickHouse的速度和功能,尝试在云上使用ClickHouse。

联系我们

手机号:13910395701

邮箱:Tracy.Wang@clickhouse.com

满足您所有的在线分析列式数据库管理需求

用户行为分析-埋点实时数仓实践(附用户关联源码) 一、概述 埋点采集、用户行为分析、实时数仓、IdMapping 此文重点讲述埋点的数据模型、数据格式、数据实时采集、加工、存储及用户关联。关于用户行为分析的概念、意义以及埋点相关的东西此文不作赘述; 二、数据模型 业界比较流行的事件、用户模型;即: * who: 设备ID、登录ID * when: 事件发生时间、上报时间 * where: 设备环境、网络环境、业务环境等 * what: 事件标识、事件参数 我们的数据存储也只有events和users两张表 阅读详情

相关推荐

ClickHouse数据迁移避坑指南:从手动导出到clickhouse-backup实战

本文详细探讨了ClickHouse数据迁移的完整流程,从手动导出导入的常见陷阱到使用clickhouse-backup工具的最佳实践。文章重点分析了CSV格式的局限性、文件系统拷贝的风险,并深入讲解了clickhouse-backup的配置、备份策略及迁移过程中的关键检查点,旨在帮助DBA和开发人员高效、安全地完成TB/PB级数据迁移。

weixin_29067143的博客 260

2022-09-05 ClickHouse的IN操作符说明

如果您已经为此情况做好准备,并且已经将数据分散到群集服务器上,以便单个用户Id的数据完全驻留在单个服务器上,则这将正常和最佳地工作。IN子句中的子查询始终只在单个服务器上运行一次。运算符的右侧可以是一组常量表达式、一组带有常量表达式的元组(如上面的示例所示),或括号中的数据库表或SELECT子查询的名称。如果运算符的右侧是具有Set引擎的表名(始终位于RAM中的准备好的数据集),则不会为每个查询重新创建数据集。换句话说,IN子句中的数据集将在每台服务器上独立收集,仅在每台服务器上本地存储的数据中收集。

悟世之路 4017

Python连接ClickHouse踩坑实录:从Client到SQLAlchemy的完整避坑指南

本文详细介绍了Python连接ClickHouse的实战经验,从基础连接到SQLAlchemy集成,涵盖了常见错误解决方案、连接池优化及性能调优技巧。特别针对clickhouse-driver和clickhouse-sqlalchemy的使用进行了深入解析,帮助开发者高效对接ClickHouse数据库。

weixin_29056701的博客 242

clickhouse因索引创建失败导致查不到指定数据_ClickHouse集群实践经验从0到1

作者:LittleMagic链接:https://www.jianshu.com/p/363d734bdc03来源:简书著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。前言经过一个月的调研和快速试错,我们的ClickHouse集群已经正式投入生产环境,在此过程中总结出了部分有用的经验,现记录如下。看官可去粗取精,按照自己项目中的实际情况采纳之。(版本为19.16.14...

weixin_42397024的博客 1287

大数据领域 ClickHouse 的数据备份与恢复方案

工具全量/增量支持存储加密压缩企业级特性成本适用场景支持本地/S3/GCS是是无免费所有场景(首选)支持本地/S3/GCS是是有收费大型企业集群手动备份仅全量本地无无无免费测试环境小集群ClickHouse的备份恢复不是"可选功能",而是生产环境的必备防线。原理是基础:理解MergeTree的存储结构,才能设计合理的备份策略;工具选对省一半力:clickhouse-backup是官方首选,功能全面;策略要落地。

2501_92132293的博客 895

ClickHouse查询避坑指南:别再被Nullable字段的空值坑了,IFNULL/COALESCE实战详解

本文深入解析ClickHouse中Nullable字段的空值处理问题,提供IFNULL、COALESCE和NULLIF等函数的实战应用指南。通过典型场景示例和性能优化建议,帮助开发者避免查询陷阱,提升数据处理效率。特别针对聚合查询、JOIN操作等复杂场景,给出详细的解决方案和最佳实践。

weixin_30414305的博客 419

ClickHouse安装避坑指南:从零开始搭建你的第一个分析数据库

本文详细介绍了ClickHouse分析数据库的安装与配置避坑指南,从系统环境准备到性能调优,手把手教你搭建生产可用的ClickHouse环境。涵盖文件描述符调整、透明大页关闭、关键配置优化等实用技巧,帮助开发者避免常见错误,提升数据库性能。

weixin_29061821的博客 393

ClickHouse新手避坑指南:我踩过的10个常见异常及修复方法(附版本号)

本文详细介绍了ClickHouse新手在使用过程中常见的10个异常问题及其修复方法,涵盖类型系统、资源管理、分布式环境、SQL编写等多个方面。特别针对20.x至21.x版本中的典型错误,提供了实战解决方案和优化建议,帮助开发者快速掌握ClickHouse异常处理技巧,提升数据库使用效率。

weixin_30839881的博客 457

ClickHouse生产环境12个致命坑:从部署到查询的避坑全指南

ClickHouse作为高性能列式数据库,以极速查询著称,但在真实生产环境中,真正考验工程师的往往是那些隐藏的使用陷阱。从连接端口混乱、用户认证失败,到Too many parts导致写入拒绝、ZooKeeper会话过期引发副本断裂,再到mutation阻塞集群、分布式表异步写入延迟、深分页拖垮CPU——每一个看似普通的环节都可能演变成重大事故。本文将基于实际生产经验,系统梳理部署、写入、表结构、集群和查询五个维度的常见问题,深入剖析其底层原理,并给出可落地的排查思路与优化方案。无论是ClickHouse初

weixin_32705179的博客 307

ClickHouse高级数据查询SQL: WITH/JOIN/IN/INTO OUTFILE/嵌套子查询/交并差计算等

本文目录1.1. SQL概述1.1.1. SQL简史1.1.2. SQL概述1.1.3. ClickHouse SQL1.1.4. ClickHouse 查询分类1.2. 数据查询1.2.1. 概述1.2.2. WITH子句1.2.3. FROM子句1.2.4. SAMPLE子句1.2.5. JOIN子句1.2.6. PREWHERE子句1.2.7. WHERE子句1....

AI天才研究院 1万+

树莓派4B(Raspbian buster系统)安装ROS Melodic(附带网络配置和远程桌面控制说明)

树莓派4B(Raspbian buster系统)安装ROS Melodic(附带网络配置和远程桌面控制说明) 一、硬件准备 二、软件准备 三、安装前的准备工作 四、开始ROS的安装 五、运行小乌龟 由于坑比较多希望大家安装的时候尽量不要跳步进行,一定要等每一步运行成功了再往下进行。 一、硬件准备 1、树莓派4B一个 2、SD卡一张(最好是16G以上的我的是用的64G的) 3、显示器、键盘、鼠标 二、软件准备 1、Raspberryimage (写系统使用的) 链接:https://pan.baidu.com

weixin_45315065的博客 1万+

多维聚合中的数据操纵:从ClickHouse实战到避坑指南

多维聚合(Multi-Dimensional Aggregation)是现代OLAP分析的核心范式,它突破传统SQL中GROUP BY的静态维度绑定,将数据建模为可动态切片、旋转与折叠的N维立方体。其技术价值在于支撑实时、灵活、跨业务视角的下钻与上卷分析,广泛应用于BI报表、风控建模、实时看板等场景。而Data Manipulation in Multi-Dimensional Aggregation——即在聚合过程中对维度、函数、条件、层级和结果的全程干预能力——决定了系统能否兼顾性能、准确与敏捷。本文聚

weixin_33725126的博客 415

Python实战:3步搞定视频去重,告别重复文件烦恼(附完整代码)

本文提供了一套基于Python的视频去重实战方案,通过三步流程(抽帧、生成内容指纹、相似度比对)高效识别重复视频文件。文章详细介绍了使用dHash算法生成视频指纹的核心原理,并提供了完整的代码实现,帮助用户快速构建自己的视频去重工具,告别重复文件管理烦恼。

weixin_29054245的博客 380

ClickHouse安装包怎么选?版本、下载渠道与部署避坑全指南

在OLAP大数据分析场景中,ClickHouse凭借极速查询性能成为众多企业的首选列式数据库。不过很多开发者在搭建集群时,第一步就卡在安装包下载与版本选型上:LTS与普通版如何取舍?rpm、deb、tgz三种包形态该选哪个?镜像源与离线包又该如何配合?这些看似基础的问题,往往决定了后续建表、查询能否顺利跑通。本文从环境部署的通用技术点入手,系统梳理ClickHouse安装包下载的完整链路——从版本号识别、官方下载页结构、公共镜像同步,到tgz/rpm/deb实操流程、SHA256完整性校验、依赖库与系统权限

weixin_33600816的博客 293

【C++】lambda表达式

本篇文章我们要学习的是lambda表达式,它是C++11新增的一种特别方便的语法,相较于之前的函数指针以及仿函数都方便了不少,下面就让我们一起来学习吧。

malloc不出对象的博客 2630

如何在OBS中添加实时时间戳:Lua脚本配置教程(附效果展示)

本文详细介绍了如何在OBS中通过Lua脚本配置实时时间戳功能,包括环境准备、脚本获取、安装配置及高级定制。适用于直播和视频录制场景,提供精准回溯和风格自定义,支持多平台适配和性能优化,是专业制作的必备技巧。

day7的博客 1044

JMeter连接ClickHouse压测配置全攻略:驱动、连接池与SQL方言避坑指南

性能压测中,数据库连接配置往往是链路稳定性的第一道关卡。JDBC作为Java生态的通用接口,其驱动类、URL规范和连接池参数直接决定测试工具能否高效访问目标数据库。ClickHouse作为列式分析数据库,凭借独有的HTTP/原生TCP双协议和SQL方言,给JMeter压测带来了额外复杂度。从驱动选型到端口逻辑,再到连接池配比与查询兼容性,本文系统梳理了JMeter接入ClickHouse的完整配置链路,并结合ClassNotFoundException、连接池超时等典型故障给出排查方向,帮助测试工程师快速搭

weixin_31423955的博客 127

11.Labview实现用户界面切换的几种方式---通过VI间相互调用

本文介绍了界面切换的几种方式,分别是重入和引用①重入方式可以通过调用子VI的方式打开被调用的界面,往往应用于弹窗等的设置程序。②引用方式分两种,一种是打开引用,一种是静态引用。区别在于打开引用需要设置被打开VI的目标地址,静态引用仅需在引用时绑定VI的位置即可。③推荐使用静态引用的方式切换界面。④使用引用打开界面时,需通过属性节点和调用节点来设置程序的状态。更多内容欢迎大家补充和留言讨论~本文介绍了GUI界面设计相关的程序,更多相关文章后续持续更新,请关注作者不迷路~本期就到这里,再见~

关注我,更多技术问题欢迎私聊~ 9546

DataX JSON配置实战:从MySQL到ClickHouse的性能调优与避坑指南

本文详细解析了DataX JSON配置在MySQL到ClickHouse数据同步中的实战应用,重点介绍了性能调优与常见问题解决方案。通过speed参数优化、errorLimit容错机制、reader/writer模块配置技巧等核心内容,帮助开发者高效完成数据同步任务,避免常见陷阱。

weixin_29196613的博客 252

ABB变频器使用PROFINET IO通信模块时的激活方法

ABB变频器使用PROFINET IO通信模块时的激活方法

Robot_PLC_HMI_Automation 2734

thinkphp 微信商户转账到微信用户零钱(v3密钥版)(含SDK和文档)

一种是用v3密钥的接口:微信商户转账到零钱(听说是v2接口的微信商户容易被限制,后来就改成v3了)这几天做项目有一个需求,小程序用户提交记录后,商家后台审核通过自动转账到用户的微信零钱中.今天分享下如何实现自动打款,v3微信商户转账到零钱。接口返回状态查看原因。

hanzhuhuaa的博客 428

ClickHouse单机版安装避坑指南:从配置调优到服务验证(附常见错误解决方案)

本文详细介绍了ClickHouse单机版的安装与配置调优,涵盖环境准备、系统调优、安装过程中的常见问题及解决方案,以及服务验证和性能调优实战。特别针对单节点部署中的内存配置、端口冲突等典型问题提供了实用指南,帮助用户高效完成ClickHouse的安装与优化。

python9snake的博客 161

一步步教你使用 NVIDIA 推出的全新GPU加速求解器 cuOpt:解锁超高效率的求解体验

未完成

Linshaodan520的博客 869

clickhouse 类型错误、聚合函数错误——字段别名的注意事项

最近接触了clickhouse,不得不说性能是真的强大,即使最简单的使用,不加任何优化也比常规数据库要快上很多,所以一直把它当作普通数据库来用,也支持sql语句,上手起来很快,不过今天写需求时用到了case when语句,从而引出了clickhouse字段别名的一些用法。 首先说一下别名指的是:select columnA as columnB 这种用法。 (得出的结论均为自己摸索,未查到相关资料,如有错误多多指正) 最大不同:上一个字段的别名可在下面的字段中直接使用 这个是接触ck时最不习惯的问题,因为以

qq_42265026的博客 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

上一篇: ClickHouse中的异步数据插入
下一篇: 一文教你使用ClickHouse的字典(dictionary)
ClickHouseDB
博客等级 码龄3年 1707粉丝 320原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值