27 Matching Annotations
  1. Jun 2022
    1. 根据个人猜测,可能是为了控制primary.idx文件的大小。order by 决定了数据写入文件的顺序,primary key 决定了索引文件primary.idx的大小。如果order by指定的字段过大,可能会导致索引文件超级大,影响查询效率。此时可以通过单独指定primary key来解决这个问题。

      order by和primary key

    2. 当然为了防止出现小文件问题,ch有后台进程合并文件夹,减少小文件的负担。
    3. 向clickhouse插入数据的时候,每次insert都会产生一个文件夹

      1、每次去找上次插入生成的文件会有多余的耗时,追加不如新建快; 2、文件内的数据是order by的,如果在已有的排好序的序列插入需要插入排序; 3、直接生成新文件,就是多个排好序的文件再合并,直接归并排序;

    1. 值得一提的是,通常只有在使用SummingMergeTree或AggregatingMergeTree的时候,才需要同时设置ORDER BY与PRIMARY KEY。 显式的设置PRIMARY KEY,是为了将主键和排序键设置成不同的值,是进一步优化的体现。
    1. 对于表的并发访问,我们使用多版本机制。换言之,当一张表同时被读和更新时,数据从当前查询到的一组片段中读取。没有冗长的的锁。插入不会阻碍读取。对表的读操作是自动并行的。

      没懂?

    2. 每个数据片段被逻辑的分割成颗粒(granules)。颗粒是 ClickHouse 中进行数据查询时的最小不可分割数据集。ClickHouse 不会对行或值进行拆分,所以每个颗粒总是包含整数个行。每个颗粒的第一行通过该行的主键值进行标记, ClickHouse 会为每个数据片段创建一个索引文件来存储这些标记。

      1、颗粒是最小的不可分割数据集 2、不会对行或列进行拆分,每个颗粒包含整数个行 3、每个数据片段创建一个索引文件

    3. Compact 格式可以提高插入量少插入频率频繁时的性能。
    4. 因此,仅使用日期而没有用主键字段作为条件的查询将会导致需要读取超过这个指定日期以外的数据。
    5. 在块中,数据按主键排序,主键第一列可能不包含日期
    6. 要检查 ClickHouse 执行一个查询时能否使用索引,可设置 force_index_by_date 和 force_primary_key 。
    7. 对排序键进行 ALTER 是轻量级的操作,因为当一个新列同时被加入到表里和排序键里时,已存在的数据片段并不需要修改。由于旧的排序键是新排序键的前缀,并且新添加的列中没有数据,因此在表修改时的数据对于新旧的排序键来说都是有序的。
    8. 但这将导致排序键中包含大量的列,并且排序键会伴随着新添加的维度不断的更新。在这种情况下合理的做法是,只保留少量的列在主键当中用于提升扫描效率,将维度列添加到排序键中。
    9. 由于 SummingMergeTree 和 AggregatingMergeTree 会对排序键相同的行进行聚合,所以把所有的维度放进排序键是很自然的做法
    10. 可以使用 ORDER BY tuple() 语法创建没有主键的表。在这种情况下 ClickHouse 根据数据插入的顺序存储。如果在使用 INSERT ... SELECT 时希望保持数据的排序,请设置 max_insert_threads = 1。
    1. 该命令将表的排序键更改为 new_expression(表达式或表达式元组)。主键保持不变。

      新增排序列(order by)

  2. May 2022
    1. 通过ClickHouse官方的JDBC向ClickHouse中批量写入数据时,必须控制每个批次的数据中涉及到的分区的数量,在写入之前最好通过Order By语句对需要导入的数据进行排序。无序的数据或者数据中涉及的分区太多,会导致ClickHouse无法及时的对新导入的数据进行合并,从而影响查询性能。

      写入之前进行排序,无序的数据会导致无法及时对新数据进行合并

    2. 为每一个账户添加join_use_nulls配置。ClickHouse的SQL语法是非标准的,默认情况下,以Left Join为例,如果左表中的一条记录在右表中不存在,右表的相应字段会返回该字段相应数据类型的默认值,而不是标准SQL中的Null值。对于习惯了标准SQL的我们来说,这种返回值经常会造成困扰。

      join_use_nulls

    3. zookeeper压力太大,clickhouse表处于”read only mode”,插入失败
    4. 建表的时候添加use_minimalistic_part_header_in_zookeeper参数,对元数据进行压缩存储
    5. 上面有说过clickhouse对zookeeper的依赖非常的重,表的元数据信息,每个数据块的信息,每次插入的时候,数据同步的时候,都需要和zookeeper进行交互,上面存储的数据非常的多。
    6. 分区字段的设置要慎重考虑,如果每次插入涉及的分区太多,那么不仅容易出现上面的异常,同时在插入的时候也比较耗时,原因是每个数据目录都需要和zookeeper进行交互。
    7. 文件夹的生成速度太快,merge速度跟不上了,所以官方文档的上每秒不超过1个插入请求,更准确的说是每秒不超过1个数据目录。
    8. 当order by已使用max_bytes_before_external_sort内存就进行溢写磁盘(基于磁盘排序),如果不设置该值,那么当内存不够时直接抛错,设置了该值order by可以正常完成,但是速度相对存内存来说肯定要慢点(实测慢的非常多,无法接受)
    9. 在进行group by的时候,内存使用量已经达到了max_bytes_before_external_group_by的时候就进行写磁盘(基于磁盘的group by相对于基于磁盘的order by性能损耗要好很多的),一般max_bytes_before_external_group_by设置为max_memory_usage / 2,原因是在clickhouse中聚合分两个阶段:
    10. 对于JOIN场景,我们需要注意的是clickhouse在进行JOIN的时候都是将"右表"进行多节点的传输的(右表广播)

      分布式场景? join小表放在右边?

  3. Mar 2020