精华内容
下载资源
问答
  • 全网最细最全clickhouse教程(clickhouse视频教程)

    千次阅读 多人点赞 2020-08-26 16:25:30
    1 ClickHouse ClickHouse 2 Aug 5 14:43 primary.idx - *.bin是按列保存数据的文件 - *.mrk保存块偏移量 - primary.idx保存主键索引 合并多次插入数据的分区 optimize table tb_merge_tree ; 再合并一次 ...

    表引擎(即表的类型)决定了:

    1. 数据的存储方式和位置,写到哪里以及从哪里读取数据
    2. 支持哪些查询以及如何支持。
    3. 并发数据访问。
    4. 索引的使用(如果存在)。
    5. 是否可以执行多线程请求。
    6. 数据复制参数。

    在读取时,引擎只需要输出所请求的列,但在某些情况下,引擎可以在响应请求时部分处理数据。对于大多数正式的任务,应该使用MergeTree族中的引擎。视频地址

     

    1 日志系列

    具有最小功能的轻量级引擎。当您需要快速写入许多小表(最多约100万行)并在以后整体读取它们时,该类型的引擎是最有效的。

     

    1.1 StripeLog

    在你需要写入许多小数据量(小于一百万行)的表的场景下使用这个引擎。

    -- 建表
    CREATE TABLE stripe_log_table(
        timestamp DateTime,
        message_type String,
    message String)ENGINE = StripeLog ;
    -- 插入数据
    
    INSERT INTO stripe_log_table VALUES (now(),'Title','多易教育') ;
    INSERT INTO stripe_log_table VALUES (now(),'Subject','大数据'),(now(),'WARNING','学大数据到多易教育') ;

     

    StripeLog 引擎将所有列存储在一个文件中。对每一次 Insert 请求,ClickHouse 将数据块追加在表文件的末尾,逐列写入。

    ClickHouse 为每张表写入以下文件:

    data.bin — 数据文件。

    index.mrk — 带标记的文件。标记包含了已插入的每个数据块中每列的偏移量。

    StripeLog 引擎不支持 ALTER UPDATE 和 ALTER DELETE 操作。

    读数据

    带标记的文件使得 ClickHouse 可以并行的读取数据。这意味着 SELECT 请求返回行的顺序是不可预测的。使用 ORDER BY 子句对行进行排序。

    我们使用两次 INSERT 请求从而在 data.bin 文件中创建两个数据块。

    ClickHouse 在查询数据时使用多线程。每个线程读取单独的数据块并在完成后独立的返回结果行。这样的结果是,大多数情况下,输出中块的顺序和输入时相应块的顺序是不同的。例如:

    select * from  stripe_log_table ;

    1.2 TinyLog

    最简单的表引擎,用于将数据存储在磁盘上。每列都存储在单独的压缩文件中,写入时,数据将附加到文件末尾。

    该引擎没有并发控制,不允许并发操作

        - 只支持并发读

        - 如果同时从表中读取和写入数据,则读取操作将抛出异常;

        - 如果同时写入多个查询中的表,则数据将被破坏。

    -- 建表 
    create table tb_tinylog(id Int8 , name String , age Int8) engine=TinyLog ;
    -- 插入数据
    insert into tb_tinylog values(1,'马云',56),(2,'马化腾',55),(3,'马克思',123) ;
    -- 查询数据
    SELECT * FROM tb_tinylog
    ┌─id─┬─name───┬─age─┐
    │  1 │ 马云   │  56 │
    │  2 │ 马化腾 │  55 │
    │  3 │ 马克思 │ 123 │
    └────┴────────┴─────┘

    查看磁盘中存储的数据

    数据存储在机器的磁盘上,每列一个文件,插入数据向列文件的后面追加 

    再插入一条数据后, 存储列数据的文件的大小增加了

    age.bin 和 id.bin,name.bin 是压缩过的对应的列的数据,sizes.json 中记录了每个 *.bin 文件的大小:

    cat sizes.json

    {"yandex":{"age%2Ebin":{"size":"56"},"id%2Ebin":{"size":"56"},"name%2Ebin":{"size":"87"}}

    这种表引擎的典型用法是 write-once:首先只写入一次数据,然后根据需要多次读取。此引擎适用于相对较小的表(建议最多1,000,000行)。如果有许多小表,则使用此表引擎是适合的,因为它比需要打开的文件更少。当拥有大量小表时,可能会导致性能低下。 不支持索引。

    1.3 Log

    日志与 TinyLog 的不同之处在于,«标记» 的小文件与列文件存在一起。这些标记写在每个数据块上,并且包含偏移量,这些偏移量指示从哪里开始读取文件以便跳过指定的行数。这使得可以在多个线程中读取表数据。对于并发数据访问,可以同时执行读取操作,而写入操作则阻塞读取和其它写入。Log 引擎不支持索引。同样,如果写入表失败,则该表将被破坏,并且从该表读取将返回错误。Log 引擎适用于临时数据,write-once 表以及测试或演示目的。

    -- 建表
    create table tb_log(id Int8 , name String , age Int8) engine=Log ;
    --插入数据
    insert into tb_log values(1,'马云',56),(2,'马化腾',55),(3,'马克思',123) ;
    insert into tb_log values(4,'Hangge',26),(5,'Taoge',35),(6,'Xingge',45) ;

    1.4 总结

    共同属性

    数据存储在磁盘上。

    写入时将数据追加在文件末尾。

    不支持突变操作。

    不支持索引。

    这意味着 `SELECT` 在范围查询时效率不高。

    非原子地写入数据。

    如果某些事情破坏了写操作,例如服务器的异常关闭,你将会得到一张包含了损坏数据的表。

    差异

    Log 和 StripeLog 引擎支持:

    并发访问数据的锁。

    `INSERT` 请求执行过程中表会被锁定,并且其他的读写数据的请求都会等待直到锁定被解除。如果没有写数据的请求,任意数量的读请求都可以并发执行。

    并行读取数据。

    在读取数据时,ClickHouse 使用多线程。 每个线程处理不同的数据块。

    Log 引擎为表中的每一列使用不同的文件。StripeLog 将所有的数据存储在一个文件中。因此 StripeLog 引擎在操作系统中使用更少的描述符,但是 Log 引擎提供更高的读性能。

    TinyLog 引擎是该系列中最简单的引擎并且提供了最少的功能和最低的性能。TingLog 引擎不支持并行读取和并发数据访问,并将每一列存储在不同的文件中。它比其余两种支持并行读取的引擎的读取速度更慢,并且使用了和 Log 引擎同样多的描述符。你可以在简单的低负载的情景下使用它。

     

    2 MergeTree系列

        MergeTree系列的表引擎是ClickHouse数据存储功能的核心。它们提供了用于弹性和高性能数据检索的大多数功能:列式存储,自定义分区,稀疏的主索引,辅助数据跳过索引等。

    基本MergeTree表引擎可以被认为是单节点ClickHouse实例的默认表引擎,因为它在各种用例中通用且实用。

    对于生产用途,ReplicatedMergeTree是必经之路,因为它为常规MergeTree引擎的所有功能增加了高可用性。一个额外的好处是在数据提取时自动进行重复数据删除,因此如果在插入过程中出现网络问题,该软件可以安全地重试。

    MergeTree系列的所有其他引擎为某些特定用例添加了额外的功能。通常,它是作为后台的其他数据操作实现的。

    MergeTree引擎的主要缺点是它们很重。因此,典型的模式是没有太多。如果您需要许多小表(例如用于临时数据)

    2.1 MergeTree

    2.1.1 基本语法

    CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster](
        name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
        name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
        ...
        INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
    INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2) 
    ENGINE = MergeTree()ORDER BY expr[PARTITION BY expr][PRIMARY KEY expr][SAMPLE BY expr][TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...][SETTINGS name=value, ...]

    2.1.2 参数解读

    ENGINE—引擎的名称和参数。ENGINE = MergeTree()。该MergeTree引擎没有参数。

    ORDER BY —排序键

    列名称或任意表达式的元组。范例:ORDER BY (CounterID, EventDate)。

    如果PRIMARY KEY子句未明确定义主键,则ClickHouse会将排序键用作主键。

    ORDER BY tuple()如果不需要排序,请使用语法。

    PARTITION BY— 分区键。可选的。

    要按月进行分区,请使用toYYYYMM(date_column)表达式,其中的date_column是日期类型为Date的列。此处的分区名称具有"YYYYMM"格式。

    PRIMARY KEY—主键(与排序键)不同。可选的。

    默认情况下,主键与排序键(由ORDER BY子句指定)相同。因此,在大多数情况下,无需指定单独的PRIMARY KEY子句。

    SAMPLE BY—用于采样的表达式。可选的。

    如果使用采样表达式,则主键必须包含它。范例:SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))。

    TTL—规则列表,用于指定行的存储持续时间并定义磁盘和卷之间零件自动移动的逻辑。可选的。

    结果必须有一个Date或一DateTime列。例:
    TTL date + INTERVAL 1 DAY

    规则的类型DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'指定了在满足表达式(达到当前时间)时要对零件执行的操作:删除过期的行,将零件(如果对零件中的所有行都满足表达式)移动到指定的磁盘(TO DISK 'xxx')或到音量(TO VOLUME 'xxx')。规则的默认类型为删除(DELETE)。可以指定多个规则的列表,但最多只能有一个DELETE规则。

    SETTINGS—控制MergeTree(可选)行为的其他参数:

    1. index_granularity—索引标记之间的最大数据行数。默认值:8192。请参见数据存储
    2. index_granularity_bytes—数据粒度的最大大小(以字节为单位)。默认值:10Mb。要仅按行数限制颗粒大小,请设置为0(不建议)。请参阅数据存储
    3. enable_mixed_granularity_parts—启用或禁用过渡以通过index_granularity_bytes设置控制颗粒尺寸。在版本19.11之前,只有index_granularity用于限制颗粒大小的设置。index_granularity_bytes从具有大行(数十和数百MB)的表中选择数据时,此设置可提高ClickHouse性能。如果您的表具有大行,则可以为表启用此设置以提高SELECT查询效率。
    4. use_minimalistic_part_header_in_zookeeper— ZooKeeper中数据部件头的存储方法。如果为use_minimalistic_part_header_in_zookeeper=1,则ZooKeeper存储的数据较少。有关更多信息,请参阅“服务器配置参数”中的设置说明
    5. min_merge_bytes_to_use_direct_io—使用对存储磁盘的直接I / O访问所需的最小合并操作数据量。合并数据部分时,ClickHouse会计算要合并的所有数据的总存储量。如果卷超过min_merge_bytes_to_use_direct_io字节,ClickHouse将使用直接I / O接口(O_DIRECT选项)读取数据并将数据写入存储磁盘。如果为min_merge_bytes_to_use_direct_io = 0,则直接I / O被禁用。默认值:10 * 1024 * 1024 * 1024字节。
    6. merge_with_ttl_timeout—重复与TTL合并之前的最小延迟(以秒为单位)。默认值:86400(1天)。
    7. write_final_mark—启用或禁用在数据部分的末尾(最后一个字节之后)写入最终索引标记。默认值:1.不要关闭它。
    8. merge_max_bloCK_size—合并操作的块中的最大行数。默认值:8192
    9. storage_policy—存储策略。请参阅使用多个块设备进行数据存储
    10. min_bytes_for_wide_part,min_rows_for_wide_part—可以以Wide格式存储的数据部分中的最小字节/行数。您可以设置这些设置之一,全部或全部。请参阅数据存储

    2.1.3 建表示例

    建表
    create table tb_merge_tree(
    id Int8 ,
    name String ,
    ctime Date 
    )
    engine=MergeTree()
    order by id 
    partition by name ;
    插入数据
    insert into tb_merge_tree values
    (1,'hng','2020-08-07'),(4,'hng','2020-08-07'),(3,'ada','2020-08-07'),(2,'ada','2020-08-07') ; 

    指定的分区字段是name

    指定的排序字段是id

    再次插入数据
    insert into tb_merge_tree values(5,'ada','2020-08-07'),(6,'hng','2020-08-07') ;

    每批次的插入数据作为一个基础单元进行分区,区内数据按照指定的字段进行排序

    进入到某个分区目录下

    [root@linux04 8cc7880f023bd2c11f539b5088249423_1_1_0]# ll

    total 48

    -rw-r-----. 1 ClickHouse ClickHouse 361 Aug  5 14:43 cheCKsums.txt

    -rw-r-----. 1 ClickHouse ClickHouse  74 Aug  5 14:43 columns.txt  所有的列

    -rw-r-----. 1 ClickHouse ClickHouse   1 Aug  5 14:43 count.txt   记录数据的条数

    -rw-r-----. 1 ClickHouse ClickHouse  30 Aug  5 14:43 ctime.bin

    -rw-r-----. 1 ClickHouse ClickHouse  48 Aug  5 14:43 ctime.mrk2

    -rw-r-----. 1 ClickHouse ClickHouse  28 Aug  5 14:43 id.bin

    -rw-r-----. 1 ClickHouse ClickHouse  48 Aug  5 14:43 id.mrk2

    -rw-r-----. 1 ClickHouse ClickHouse   8 Aug  5 14:43 minmax_name.idx

    -rw-r-----. 1 ClickHouse ClickHouse  34 Aug  5 14:43 name.bin

    -rw-r-----. 1 ClickHouse ClickHouse  48 Aug  5 14:43 name.mrk2

    -rw-r-----. 1 ClickHouse ClickHouse   4 Aug  5 14:43 partition.dat

    -rw-r-----. 1 ClickHouse ClickHouse   2 Aug  5 14:43 primary.idx

    - *.bin是按列保存数据的文件

    - *.mrk保存块偏移量

    - primary.idx保存主键索引

    合并多次插入数据的分区

     optimize table tb_merge_tree ;

    再合并一次  optimize table tb_merge_tree ;

    合并完以后数据在磁盘上的存储是 

    过段时间以后CK内部自动的会删除合并前的多余的文件夹

    在磁盘上的数据组织结构是

     

     

     

    2.2

    2,3

    2,4

    2.5

     

     

    3 集成引擎

    4 其他引擎

    扫码观看全部视频

    视频地址

     

    展开全文
  • ClickHouse® is an open-source column-oriented database management system that allows generating analytical data reports in real time. Useful Links Official website has quick high-level overview of...
  • clickhouse教程-09

    2020-10-14 10:08:48
    ---9-1--- 总结: 示例1: 定义常量表达式变量 WITH '2019-08-01 15:23:00' AS timestamp SELECT ...┌─number─┬─timestamp───────────┐ ...└────────┴──────..

    ---9-1---

    WITH只在查询的时候是有效的,不作为对象储存。

    查询1:

    查询2:

    with定义子查询,这个查询只能返回一行数据,但是可以有多个列。

    查询3:子查询不可以使用主查询的,反之可以的。

    查询4:

    总结:

    
    示例1: 定义常量表达式变量
    WITH '2019-08-01 15:23:00' AS timestamp
    SELECT 
        number, 
        timestamp
    FROM system.numbers
    LIMIT 2
    
    ┌─number─┬─timestamp───────────┐
    │      0 │ 2019-08-01 15:23:00 │
    │      1 │ 2019-08-01 15:23:00 │
    └────────┴─────────────────────┘
    示例2:函数表达式
    
    WITH sum(bytes) AS s
    SELECT 
        formatReadableSize(s), 
        table
    FROM system.parts
    GROUP BY table
    ORDER BY s ASC
    
    
    示例3: 在WITH子句中定义子查询,这里需注意子查询只能返回一行数据。
    这个例子将返回TOP10的大表:
    
    WITH 
        (
            SELECT sum(bytes)
            FROM system.parts
            WHERE active
        ) AS total_disk_usage
    SELECT 
        (sum(bytes) / total_disk_usage) * 100 AS table_disk_usage, 
        table
    FROM system.parts
    GROUP BY table
    ORDER BY table_disk_usage DESC
    LIMIT 10
    
    示例4:WITH子句的作用范围
    1)、子查询中不能使用主查询的WITH子句的结果,反之可以
    WITH '2020-05-01 15:23:00' AS timestamp
    SELECT 
        number, 
        date
    FROM 
    (
        SELECT 
            number, 
            toDate(timestamp) AS date
        FROM system.numbers
        LIMIT 10
    )
    上面语句尝试在子查询中引用住查询WITH子句的timestamp字段, 执行这段代码将抛出异常:
    Code: 47. DB::Exception: Received from localhost:9001. DB::Exception: Missing columns: 'timestamp' while processing query: 'SELECT number, toDate(timestamp) AS date FROM system.numbers LIMIT 10', required columns: 'number' 'timestamp', source columns: 'number'.
    
    
    下面的查询可以正常工作:
    select date, number
    from
    (
    with '2020-05-01 15:23:00' AS timestamp
    select number, toDate(timestamp) as date from system.numbers limit 10
    )
    
    
    2)、主查询不可以使用子查询内部WITH子句的结果
    select timestamp, number
    from
    (
    with '2020-05-01 15:23:00' AS timestamp
    select number, toDate(timestamp) as date from system.numbers limit 10
    )
    上面的查询尝试在主查询中使用子查询WITH子句的timestamp字段,执行这段代码将抛出异常:
    Code: 47. DB::Exception: Received from localhost:9001. DB::Exception: Missing columns: 'timestamp' while processing query: 'SELECT timestamp, number FROM (WITH '2020-05-01 15:23:00' AS timestamp SELECT number, toDate(timestamp) AS date FROM system.numbers LIMIT 10)', required columns: 'timestamp' 'number', source columns: 'date' 'number'.
    
    正确的使用方式是将WITH子句的结果作为SELECT的列返回:
    SELECT 
        timestamp, 
        number
    FROM 
    (
        WITH '2020-05-01 15:23:00' AS timestamp
        SELECT 
            number, 
            toDate(timestamp) AS date, 
            timestamp
        FROM system.numbers
        LIMIT 10
    )
    

    只能是一行数据但是可以包含多个列。

    关于with和from:https://blog.csdn.net/vkingnew/article/details/107088370

    ---9-2---

    总结:

    示例1:从表中查询数据
    SELECT * FROM system.numbers LIMIT 5
    
    
    示例2: 从子查询查询数据
    SELECT number FROM ( SELECT number FROM system.numbers LIMIT 5 )
    
    
    示例3:从表函数查询数据
    SELECT * FROM numbers(0, 5)

    ---9-3---

    只是查询一部分数据的。

    要比inidex_granularity(8192)大很多。

    例子:

    SAMPLE支持如下三种语法:
    1. SAMPLE k
    k的取值范围在0到1之间。
    
    SELECT
        Title,
        count() * 10 AS PageViews
    FROM hits_v1
    SAMPLE 0.1
    WHERE
        CounterID = 34
    GROUP BY Title
    ORDER BY PageViews DESC LIMIT 1000
    
    这个示例按照10%的比例采样数据并进行聚合计算,因此聚合计数的结果要放大十倍,这里手工乘以了一个采样系数10。
    采样系数的值也可以从表的虚拟列_sample_factor获取,这个虚拟列在建表的时候创建,在查询的时候动态计算值。 
    
    
    SELECT 
        factor, 
        count() * factor AS cnt
    FROM 
    (
        SELECT 
            CounterID, 
            _sample_factor AS factor
        FROM hits_v1
        SAMPLE 1 / 10
    )
    GROUP BY factor
    ​
    ┌─factor─┬─────cnt─┐
    │     10 │ 8398890 │
    └────────┴─────────┘
    
    
    2. SAMPLE n
    
    指定行数采样数据。
    
    SELECT count() FROM hits_v1 SAMPLE 100000
    ​
    ┌─count()─┐
    │   87591 │
    └─────────┘
    
    
    当指定行数采样数据,用户并不知道采样的百分比,因此无法手工设置采样系数系数的值,但可通过表的虚拟列_sample_factor动态生成采样的值。
    
    
    示例1: 计算页面访问次数
    SELECT sum(PageViews * _sample_factor) FROM visits_v1 SAMPLE 10000000
    
    SELECT sum(PageViews) FROM visits_v1 ;
    ​
    ┌─sum(multiply(PageViews, _sample_factor))─┐
    │                                  6754136 │
    └──────────────────────────────────────────┘
    示例2: 计算访问数
    SELECT sum(_sample_factor) FROM visits_v1 SAMPLE 1000000
    SELECT count() FROM visits_v1
    ​
    ┌─sum(_sample_factor)─┐
    │  1651842.9757234894 │
    └─────────────────────┘
    
    示例3:计算会话平均持续时间
    Note:这里不需要使用采样系数计算平均值。
    SELECT avg(Duration) FROM visits_v1 SAMPLE 10000000
    ​
    ┌──────avg(Duration)─┐
    │ 361.43725409203375 │
    └────────────────────┘
    
    
    3. SAMPLE k OFFSET m
    
    根据采样比例和偏移比例采样数据, 这里的k和m都是0到1之间的数字,其中k表示采样的比例,m表示偏移多少比例的数据才开始采样。
    
    示例1:
    SAMPLE 1/10
    这个例子将采样10%的数据:
    [++------------------]
    
    示例2:
    SAMPLE 1/10 OFFSET 1/2
    这个例子,查询会从数据的中间开始采样,采样10%的数据。
    [----------++--------]
    
    
    SELECT 
        factor, 
        count() * factor AS cnt
    FROM 
    (
        SELECT 
            CounterID, 
            _sample_factor AS factor
        FROM hits_v1
        SAMPLE 1 / 10 OFFSET 5 / 10
    )
    GROUP BY factor
    ​
    ┌─factor─┬─────cnt─┐
    │     10 │ 8954720 │
    └────────┴─────────┘
    
    
    Note:这里的OFFSET不能设置的过大,否则可能会因为采样的数据不足导致最终的计算结果偏差很大。 
    例如:SAMPLE 5 / 10 OFFSET 9 / 10, 这个表示从数据偏移90%的位置采样50%的数据,但是从数据偏移90%的位置最多只能采集10%的数据。
    SAMPLE 0.5采集的数据:
    [++++++++++----------]
    SAMPLE 0.5 OFFSET 0.9采集的数据:
    [------------------++]
    
    
    
    

    关于sample:https://blog.csdn.net/vkingnew/article/details/107090352

    ---9-4---

    下面通过示例来演示ARRAY JOIN的使用。
    创建表和生成测试数据:
    drop table arrays_test;
    CREATE TABLE arrays_test
    (
        s String,
        arr Array(UInt8)   
    ) ENGINE = Memory;
    
    INSERT INTO arrays_test
    VALUES ('Hello', [1,2]), ('World', [3,4,5]), ('Goodbye', []);
    SELECT *
    FROM arrays_test
    ​
    ┌─s───────┬─arr─────┐
    │ Hello   │ [1,2]   │
    │ World   │ [3,4,5] │
    │ Goodbye │ []      │
    └─────────┴─────────┘
    ​
    
    
    示例1: ARRAY JOIN
    SELECT 
        s, 
        arr
    FROM arrays_test
    ARRAY JOIN arr
    ​
    ┌─s─────┬─arr─┐
    │ Hello │   1 │
    │ Hello │   2 │
    │ World │   3 │
    │ World │   4 │
    │ World │   5 │
    └───────┴─────┘
    从这个例子可以看到, 每一行拆分为多行,每一行拆分后的行数为数组的大小。即一行裂变为多行,裂变后的行数为该行数组列的数组大小。
    这里JOIN结果不包含空数组的行。
    
    
    示例2: LEFT ARRAY JOIN
    SELECT 
        s, 
        arr
    FROM arrays_test
    LEFT ARRAY JOIN arr 
    ​
    ┌─s───────┬─arr─┐
    │ Hello   │   1 │
    │ Hello   │   2 │
    │ World   │   3 │
    │ World   │   4 │
    │ World   │   5 │
    │ Goodbye │   0 │
    └─────────┴─────┘
    ​
    这里JOIN结果包含空数组的行,数组的元素设置为默认的0。
    
    
    
    
    
    当在ARRAY JOIN子句中为数组指定别名,则使用别名访问数组中元素, 通过原始名称访问数组本身。
    SELECT 
        s, 
        arr, 
        a
    FROM arrays_test
    ARRAY JOIN arr AS a
    ​
    ┌─s─────┬─arr─────┬─a─┐
    │ Hello │ [1,2]   │ 1 │
    │ Hello │ [1,2]   │ 2 │
    │ World │ [3,4,5] │ 3 │
    │ World │ [3,4,5] │ 4 │
    │ World │ [3,4,5] │ 5 │
    └───────┴─────────┴───┘
    
    
    用户可使用别名实现与外部数组的JOIN。例如:
    SELECT s, arr_external FROM arrays_test ARRAY JOIN [1, 2, 3] AS arr_external
    ​
    ┌─s───────┬─arr_external─┐
    │ Hello   │            1 │
    │ Hello   │            2 │
    │ Hello   │            3 │
    │ World   │            1 │
    │ World   │            2 │
    │ World   │            3 │
    │ Goodbye │            1 │
    │ Goodbye │            2 │
    │ Goodbye │            3 │
    └─────────┴──────────────┘
    
    
    ARRAY JOIN中可指定多个数组,数组之间使用逗号分隔, 每个数组的大小必须相等。 多个数组的ARRAY JOIN不会产生笛卡尔积,他们之间的元素是按行一一对应和按行拆分的。
    SELECT 
        s, 
        arr, 
        a, 
        num, 
        mapped
    FROM arrays_test
    ARRAY JOIN 
        arr AS a, 
        arrayEnumerate(arr) AS num, 
        arrayMap(x -> (x + 1), arr) AS mapped
    ​
    ┌─s─────┬─arr─────┬─a─┬─num─┬─mapped─┐
    │ Hello │ [1,2]   │ 1 │   1 │      2 │
    │ Hello │ [1,2]   │ 2 │   2 │      3 │
    │ World │ [3,4,5] │ 3 │   1 │      4 │
    │ World │ [3,4,5] │ 4 │   2 │      5 │
    │ World │ [3,4,5] │ 5 │   3 │      6 │
    └───────┴─────────┴───┴─────┴────────┘
    
    
     arrayEnumerate的使用示例:
    SELECT 
        s, 
        arr, 
        a, 
        num, 
        arrayEnumerate(arr)
    FROM arrays_test
    ARRAY JOIN 
        arr AS a, 
        arrayEnumerate(arr) AS num
    ​
    ┌─s─────┬─arr─────┬─a─┬─num─┬─arrayEnumerate(arr)─┐
    │ Hello │ [1,2]   │ 1 │   1 │ [1,2]               │
    │ Hello │ [1,2]   │ 2 │   2 │ [1,2]               │
    │ World │ [3,4,5] │ 3 │   1 │ [1,2,3]             │
    │ World │ [3,4,5] │ 4 │   2 │ [1,2,3]             │
    │ World │ [3,4,5] │ 5 │   3 │ [1,2,3]             │
    └───────┴─────────┴───┴─────┴─────────────────────┘
    
    
    嵌套数据类型ARRAY JOIN和数组类似,下面通过示例来演示嵌套类型ARRAY JOIN的使用。 
    创建嵌套类型的表并插入测试数据:
    CREATE TABLE nested_test
    (
        s String,
        nest Nested(
        x UInt8,
        y UInt32)
    ) ENGINE = Memory;
    ​
    INSERT INTO nested_test
    VALUES ('Hello', [1,2], [10,20]), ('World', [3,4,5], [30,40,50]), ('Goodbye', [], []);
    SELECT * FROM nested_test
    ​
    ┌─s───────┬─nest.x──┬─nest.y─────┐
    │ Hello   │ [1,2]   │ [10,20]    │
    │ World   │ [3,4,5] │ [30,40,50] │
    │ Goodbye │ []      │ []         │
    └─────────┴─────────┴────────────┘
    
    
    执行ARRAY JOIN:
    SELECT s, nest.x, nest.y FROM nested_test ARRAY JOIN nest;
    ​
    ┌─s─────┬─nest.x─┬─nest.y─┐
    │ Hello │      1 │     10 │
    │ Hello │      2 │     20 │
    │ World │      3 │     30 │
    │ World │      4 │     40 │
    │ World │      5 │     50 │
    └───────┴────────┴────────┘
    下面语句执行结果和上面示例一致,可简单理解为两个数组的ARRAY JOIN:
    SELECT s, nest.x, nest.y FROM nested_test ARRAY JOIN nest.x, nest.y;
    ​
    ┌─s─────┬─nest.x─┬─nest.y─┐
    │ Hello │      1 │     10 │
    │ Hello │      2 │     20 │
    │ World │      3 │     30 │
    │ World │      4 │     40 │
    │ World │      5 │     50 │
    └───────┴────────┴────────┘
    
    
    下面是语句, 只和嵌套接收的x字段做JOIN, 因此嵌套结构的y字段不会被拆分:
    SELECT s, nest.x, nest.y FROM nested_test ARRAY JOIN nest.x;
    ​
    ┌─s─────┬─nest.x─┬─nest.y─────┐
    │ Hello │      1 │ [10,20]    │
    │ Hello │      2 │ [10,20]    │
    │ World │      3 │ [30,40,50] │
    │ World │      4 │ [30,40,50] │
    │ World │      5 │ [30,40,50] │
    └───────┴────────┴────────────┘
    
    
    使用别名:
    SELECT s, n.x, n.y, nest.x, nest.y FROM nested_test ARRAY JOIN nest AS n;
    ​
    ┌─s─────┬─n.x─┬─n.y─┬─nest.x──┬─nest.y─────┐
    │ Hello │   1 │  10 │ [1,2]   │ [10,20]    │
    │ Hello │   2 │  20 │ [1,2]   │ [10,20]    │
    │ World │   3 │  30 │ [3,4,5] │ [30,40,50] │
    │ World │   4 │  40 │ [3,4,5] │ [30,40,50] │
    │ World │   5 │  50 │ [3,4,5] │ [30,40,50] │
    └───────┴─────┴─────┴─────────┴────────────┘
    arrayEnumerate使用:
    SELECT s, n.x, n.y, nest.x, nest.y, num FROM nested_test ARRAY JOIN nest AS n, arrayEnumerate(nest.x) AS num;
    ​
    ┌─s─────┬─n.x─┬─n.y─┬─nest.x──┬─nest.y─────┬─num─┐
    │ Hello │   1 │  10 │ [1,2]   │ [10,20]    │   1 │
    │ Hello │   2 │  20 │ [1,2]   │ [10,20]    │   2 │
    │ World │   3 │  30 │ [3,4,5] │ [30,40,50] │   1 │
    │ World │   4 │  40 │ [3,4,5] │ [30,40,50] │   2 │
    │ World │   5 │  50 │ [3,4,5] │ [30,40,50] │   3 │
    └───────┴─────┴─────┴─────────┴────────────┴─────┘
    
    
    
    

    arrayEnumerate:https://blog.csdn.net/jarry_cm/article/details/106114863

    ---9-5---

    测试数据集:
    drop table t_first;
    drop table t_second;
    drop table t_third;
    create table t_first(id String, area_id String, score UInt8) ENGINE=TinyLog;
    create table t_second(id String, name String, age UInt8) ENGINE=TinyLog;
    create table t_third(area_id String, city String) ENGINE=TinyLog;
    
    
    insert into t_first values('id001', '025', 100);
    insert into t_first values('id002', '0551', 90);
    insert into t_first values('id003', '010', 80);
    
    insert into t_second values('id001', 'xiaohe', 22);
    insert into t_second values('id002', 'xiaojiang', 23);
    insert into t_second values('id003', 'xiaohai', 34);
    
    
    insert into t_third values('025', '南京');
    insert into t_third values('0551', '合肥');
    insert into t_third values('010', '北京');
    
    数据:
    SELECT * FROM t_first
    ┌─id────┬─area_id─┬─score─┐
    │ id001 │ 025     │   100 │
    │ id002 │ 0551    │    90 │
    │ id003 │ 010     │    80 │
    └───────┴─────────┴───────┘
    
    SELECT * FROM t_second
    ┌─id────┬─name──────┬─age─┐
    │ id001 │ xiaohe    │  22 │
    │ id002 │ xiaojiang │  23 │
    │ id003 │ xiaohai   │  34 │
    └───────┴───────────┴─────┘
    ​
    SELECT * FROM t_third
    ┌─area_id─┬─city─┐
    │ 025     │ 南京 │
    │ 0551    │ 合肥 │
    │ 010     │ 北京 │
    └─────────┴──────┘
    
    
    使用JOIN ON语法关联:
    SELECT 
        t1.id, 
        t1.area_id, 
        t2.name, 
        t2.age, 
        t3.city
    FROM t_first AS t1
    LEFT JOIN t_second AS t2 ON t1.id = t2.id
    LEFT JOIN t_third AS t3 ON t1.area_id = t3.area_id
    
    ┌─t1.id─┬─t1.area_id─┬─t2.name───┬─t2.age─┬─t3.city─┐
    │ id001 │ 025        │ xiaohe    │     22 │ 南京    │
    │ id002 │ 0551       │ xiaojiang │     23 │ 合肥    │
    │ id003 │ 010        │ xiaohai   │     34 │ 北京    │
    └───────┴────────────┴───────────┴────────┴─────────┘
    使用JOIN USING关联:
    SELECT 
        t1.id, 
        t1.area_id, 
        t2.name, 
        t2.age
    FROM t_first AS t1
    LEFT JOIN t_second AS t2 USING id;
    Note: USING只支持两张表之间的关联。
    
    
    多表之间逗号分隔的JOIN:
    SELECT t1.id, t1.area_id, t2.name, t2.age, t3.city
    FROM t_first AS t1, t_second AS t2, t_third AS t3
    WHERE t1.id = t2.id AND t1.area_id = t3.area_id

    ---9-6---

    关于left join和right join:https://www.cnblogs.com/bad-robot/p/9788959.html

    
    
    
    准备测试数据:
    drop table t_left;
    drop table t_right;
    create table t_left(id String, name String, ev_time DateTime, event String) ENGINE=TinyLog;
    create table t_right(id String, name String, ev_time DateTime, event String) ENGINE=TinyLog;
    
    insert into t_left values
    ('1', 'xiaojiang', '2020-03-25 23:25:55', 'event_left_1'),
    ('2', 'xiaojiang', '2020-03-25 23:25:55', 'event_left_2_1')
    ('2', 'xiaojiang', '2020-03-25 23:27:50', 'event_left_2_2')
    ('3', 'xiaojiang', '2020-03-25 23:26:22', 'event_left_3');
    
    insert into t_right values
    ('1', 'xiaojiang', '2020-03-25 23:25:20', 'event_right_1_1'),
    ('1', 'xiaojiang', '2020-03-25 23:25:55', 'event_right_1_2')
    ('2', 'xiaojiang', '2020-03-25 23:25:55', 'event_right_2_1')
    ('2', 'xiaojiang', '2020-03-25 23:26:55', 'event_right_2_2')
    ('2', 'xiaojiang', '2020-03-25 23:27:55', 'event_right_2_3');
    
    
    1 ALL
    如果右表具有多个匹配的行, ClickHouse将从匹配的行创建笛卡尔积。这是SQL中的标准JOIN行为。
    t_left表的数据:
    SELECT * FROM t_left
    ┌─id─┬─name──────┬─────────────ev_time─┬─event──────────┐
    │ 1  │ xiaojiang │ 2020-03-25 23:25:55 │ event_left_1   │
    │ 2  │ xiaojiang │ 2020-03-25 23:25:55 │ event_left_2_1 │
    │ 2  │ xiaojiang │ 2020-03-25 23:27:50 │ event_left_2_2 │
    │ 3  │ xiaojiang │ 2020-03-25 23:26:22 │ event_left_3   │
    └────┴───────────┴─────────────────────┴────────────────┘
    t_right表的数据:
    
    SELECT * FROM t_right
    ┌─id─┬─name──────┬─────────────ev_time─┬─event───────────┐
    │ 1  │ xiaojiang │ 2020-03-25 23:25:20 │ event_right_1_1 │
    │ 1  │ xiaojiang │ 2020-03-25 23:25:55 │ event_right_1_2 │
    │ 2  │ xiaojiang │ 2020-03-25 23:25:55 │ event_right_2_1 │
    │ 2  │ xiaojiang │ 2020-03-25 23:26:55 │ event_right_2_2 │
    │ 2  │ xiaojiang │ 2020-03-25 23:27:55 │ event_right_2_3 │
    └────┴───────────┴─────────────────────┴─────────────────┘
    ALL关联示例:
    SELECT 
        t1.id AS id, 
        t1.event AS event1, 
        t2.event AS event2
    FROM t_left AS t1
    ALL LEFT JOIN t_right AS t2 ON t1.id = t2.id
    ORDER BY id ASC
    ​
    ┌─id─┬─event1─────────┬─event2──────────┐
    │ 1  │ event_left_1   │ event_right_1_1 │
    │ 1  │ event_left_1   │ event_right_1_2 │
    │ 2  │ event_left_2_1 │ event_right_2_1 │
    │ 2  │ event_left_2_1 │ event_right_2_2 │
    │ 2  │ event_left_2_1 │ event_right_2_3 │
    │ 2  │ event_left_2_2 │ event_right_2_1 │
    │ 2  │ event_left_2_2 │ event_right_2_2 │
    │ 2  │ event_left_2_2 │ event_right_2_3 │
    │ 3  │ event_left_3   │                 │
    └────┴────────────────┴─────────────────┘
    
    
    2 ANY 
    如果右表具有多个匹配行,则仅连接找到的第一个行。如果右表只有一个匹配行,则使用ANY和ALL关键字的查询结果是相同的。
    SELECT 
        t1.id AS id, 
        t1.event AS event1, 
        t2.event AS event2
    FROM t_left AS t1
    ANY LEFT JOIN t_right AS t2 ON t1.id = t2.id
    ORDER BY id ASC
    
    ┌─id─┬─event1─────────┬─event2──────────┐
    │ 1  │ event_left_1   │ event_right_1_1 │
    │ 2  │ event_left_2_1 │ event_right_2_1 │
    │ 2  │ event_left_2_2 │ event_right_2_1 │
    │ 3  │ event_left_3   │                 │
    └────┴────────────────┴─────────────────┘
    
    
    3 ASOF  
    用于连接不完全匹配的序列。
    
    用于ASOF JOIN的表必须具有满足有序序列的特性的列, 这些数据类型包括:UInt32、UInt64、Float32、Float64、Date和DateTime。
    ASOF JOIN不支持JOIN引擎表。
    
    
    ASOF JON ...ON语法:
    SELECT expressions_list
    FROM table_1
    ASOF LEFT JOIN table_2
    ON equi_cond AND closest_match_cond
    
    ASOF JON支持任意个(1个或以上)相等条件和有且仅一个的不等匹配条件(最接近的匹配条件)。
    不等匹配条件(最接近的匹配条件)支持:>、>=、< 和 <=。
    
    例如:
    SELECT count() FROM table_1 ASOF LEFT JOIN table_2 ON table_1.a == table_2.b AND table_2.t <= table_1.t
    ASOF JOIN ... USING的语法:
    SELECT expressions_list
    FROM table_1
    ASOF JOIN table_2
    USING (equi_column1, ... equi_columnN, asof_column)
    
    ASOF JOIN使用equi_columnX进行相等条件连接,使用asof_column进行最接近的匹配,匹配条件为table_1.asof_column >= table_2.asof_column。asof_column是USING子句中最后一个字段。从ASOF JOIN ...USING语法,我们可以看出它的使用不如ASOF JOIN ...ON灵活,但是语句相对简单。
    
    
    ┌─id─┬────────ev_time──────┬─event_left─────┬    ┬───id─┬───────ev_time───────┬─event_right─────┐
    │ 1  │ 2020-03-25 23:25:55 │ event_left_1   │    │ 1    │ 2020-03-25 23:25:20 │ event_right_1_1 │
    │ 2  │ 2020-03-25 23:25:55 │ event_left_2_1 │    │ 1    │ 2020-03-25 23:25:55 │ event_right_1_2 │
    │ 2  │ 2020-03-25 23:27:50 │ event_left_2_2 │    │ 2    │ 2020-03-25 23:25:55 │ event_right_2_1 │
    └────┴─────────────────────┴────────────────┴    │ 2    │ 2020-03-25 23:26:55 │ event_right_2_2 │
                                                     │ 2    │ 2020-03-25 23:27:55 │ event_right_2_3 │
                                                     ┴──────┴─────────────────────┴─────────────────┘
    例如上面的数据, 使用id作为相等条件, ev_time为不等条件, 这里以id=1且left.ev_time>=right.ev_time为例, 右侧id=1虽然两条记录都满足event_left>=event_right,但是很明显右侧的2020-03-25 23:25:55和左侧的2020-03-25 23:25:55更接近,因此右侧只匹配ev_time为2020-03-25 23:25:55的记录。
    
    注意返回的是最接近的记录的。
    
    
    ASOF JOIN ... ON示例:
    SELECT 
        a.id, 
        a.ev_time AS ev_time_left, 
        b.ev_time AS ev_time_right, 
        a.event AS event_left, 
        b.event AS event_right
    FROM t_left AS a
    ASOF INNER JOIN t_right AS b ON (a.id = b.id) AND (a.name = b.name) AND (a.ev_time >= b.ev_time)
    
    
    ┌─id─┬────────ev_time_left─┬───────ev_time_right─┬─event_left─────┬─event_right─────┐
    │ 1  │ 2020-03-25 23:25:55 │ 2020-03-25 23:25:55 │ event_left_1   │ event_right_1_2 │
    │ 2  │ 2020-03-25 23:25:55 │ 2020-03-25 23:25:55 │ event_left_2_1 │ event_right_2_1 │
    │ 2  │ 2020-03-25 23:27:50 │ 2020-03-25 23:26:55 │ event_left_2_2 │ event_right_2_2 │
    └────┴─────────────────────┴─────────────────────┴────────────────┴─────────────────┘
    
    
    ASOF JOIN ... USING示例:
    
    SELECT 
        a.id, 
        a.ev_time AS ev_time_left, 
        b.ev_time AS ev_time_right, 
        a.event AS event_left, 
        b.event AS event_right
    FROM t_left AS a
    ASOF INNER JOIN t_right AS b USING (id, name, ev_time)
    
    ┌─id─┬────────ev_time_left─┬───────ev_time_right─┬─event_left─────┬─event_right─────┐
    │ 1  │ 2020-03-25 23:25:55 │ 2020-03-25 23:25:55 │ event_left_1   │ event_right_1_2 │
    │ 2  │ 2020-03-25 23:25:55 │ 2020-03-25 23:25:55 │ event_left_2_1 │ event_right_2_1 │
    │ 2  │ 2020-03-25 23:27:50 │ 2020-03-25 23:26:55 │ event_left_2_2 │ event_right_2_2 │
    └────┴─────────────────────┴─────────────────────┴────────────────┴─────────────────┘
    
    
    ASOF Summary:
    (1)、 不能使用多个不等条件。
    (2)、可使用多个相等条件。
    (3)、如果有多个满足条件的记录,只会返回最接近的记录。 

    其他的:

    USING的用法:字段最后是不等,前面是相等。

    ---9-7---

    空值的处理:

    (1)、空值的填充
    默认情况下, 空值使用对应数据类型的默认值填充。
    
    
    测试数据生成:
    drop table t_null_left;
    drop table t_null_right;
    create table t_null_left(id Nullable(UInt8), name String) ENGINE=TinyLog;
    create table t_null_right(id Nullable(UInt8), score UInt8) ENGINE=TinyLog;
    
    insert into t_null_left values
    (1, 'xiaohe')
    (2, 'xiaojiang')
    ;
    
    insert into t_null_right values
    (1, 88)
    ;
    
    关联的两张表的数据如下:
    SELECT * FROM t_null_left
    
    ┌─id─┬─name──────┐
    │  1 │ xiaohe    │
    │  2 │ xiaojiang │
    └────┴───────────┘
    ​
    
    SELECT * FROM t_null_right
    
    ┌─id─┬─score─┐
    │  1 │    88 │
    └────┴───────┘
    
    
    两表左关联:
    SELECT 
        t1.id, 
        t1.name, 
        t2.score
    FROM t_null_left AS t1
    LEFT JOIN t_null_right AS t2 ON t1.id = t2.id
    
    ┌─id─┬─name──────┬─score─┐
    │  1 │ xiaohe    │    88 │
    │  2 │ xiaojiang │     0 │
    └────┴───────────┴───────┘
    从关联的输出可以看出,左侧表(t_null_left)id为2的记录在右侧表(t_null_right)中没有与之关联的记录, 这里的score填充了UInt的默认值0。
    用户可设置join_use_nulls参数,将空值填充为NULL。join_use_nulls设置默认为0,填充相应数据类型的默认值。
    设置join_use_nulls示例:
    
    ᴺᵁᴸᴸ │
    
    SET join_use_nulls = 1;
    
    SELECT t1.id, t1.name, t2.score
    FROM t_null_left AS t1
    LEFT JOIN t_null_right AS t2 ON t1.id = t2.id
    
    ┌─id─┬─name──────┬─score─┐
    │  1 │ xiaohe    │    88 │
    │  2 │ xiaojiang │  ᴺᵁᴸᴸ │
    └────┴───────────┴───────┘
    ​
    当设置了join_use_nulls,空值使用NULL填充。
    
    
    (2)、NULL值关联
    
    如果量表关联的key只要有一个为NULL,则该行不会进行JOIN。
    准备数据:
    drop table t_null_left;
    drop table t_null_right;
    create table t_null_left(id Nullable(UInt8), name String) ENGINE=TinyLog;
    create table t_null_right(id Nullable(UInt8), score UInt8) ENGINE=TinyLog;
    
    insert into t_null_left values
    (1, 'xiaohe')
    (NULL, 'xiaojiang')
    ;
    
    insert into t_null_right values
    (1, 88)
    (NULL, 90)
    ;
    ​
    两表的数据:
    SELECT * FROM t_null_left;
    
    ┌───id─┬─name──────┐
    │    1 │ xiaohe    │
    │ ᴺᵁᴸᴸ │ xiaojiang │
    └──────┴───────────┘
    
    SELECT * FROM t_null_right;
    
    ┌───id─┬─score─┐
    │    1 │    88 │
    │ ᴺᵁᴸᴸ │    90 │
    └──────┴───────┘
    
    
    两表关联:
    SELECT 
        t1.id, 
        t1.name, 
        t2.score
    FROM t_null_left AS t1
    INNER JOIN t_null_right AS t2 ON t1.id = t2.id;
    
    ┌─id─┬─name───┬─score─┐
    │  1 │ xiaohe │    88 │
    └────┴────────┴───────┘
    
    

     

    ---9-8---

    1. 验证PREWHERE读取数据的大小
    (1)、关闭PREWHERE的自动转化
    SET optimize_move_to_prewhere = 0
    (2)、使用WHERE查询
    SELECT UserID, WatchID, Title FROM hits_v1 WHERE WatchID = 9126318258181481721;
    ​
    ┌─────────────UserID─┬─────────────WatchID─┬─Title───────────────────────────────────────────────────────────┐
    │ 610708775678702928 │ 9126318258181481721 │ вышивка в Москве - Образовать фото мочия - Почта Mail.Ru: Силва │
    └────────────────────┴─────────────────────┴─────────────────────────────────────────────────────────────────┘
    ​
    1 rows in set. Elapsed: 0.094 sec. Processed 8.87 million rows, 908.92 MB (94.08 million rows/s., 9.64 GB/s.) 
    ​
    
    
    (3)、使用PREWHERE的查询
    SELECT UserID, WatchID, Title FROM hits_v1 PREWHERE WatchID = 9126318258181481721;
    ​
    ┌─────────────UserID─┬─────────────WatchID─┬─Title───────────────────────────────────────────────────────────┐
    │ 610708775678702928 │ 9126318258181481721 │ вышивка в Москве - Образовать фото мочия - Почта Mail.Ru: Силва │
    └────────────────────┴─────────────────────┴─────────────────────────────────────────────────────────────────┘
    ​
    1 rows in set. Elapsed: 0.017 sec. Processed 8.87 million rows, 70.99 MB (533.89 million rows/s., 4.27 GB/s.) 
    对比两种查询, WHERE读取了908.92 MB数据, PREWHERE只读取了70.99 MB数据,PREWHERE的耗时也明显更少。
    
    
    2. 验证PREWHERE条件的自动转移
    该示例要确保optimize_move_to_prewhere设置为1,即默认设置。
    执行语句:
    
    SELECT UserID, WatchID, Title FROM hits_v1 PREWHERE WatchID = 9126318258181481721;
    查看server的日志,可以观察到WHERE条件转移到PREWHERE子句。
    
    
    2020.03.26 17:01:02.784134 [ 73 ] {cd075c5e-45d8-4b64-bb99-fcc183c29b1c} <Debug> executeQuery: (from 127.0.0.1:37418) SELECT UserID, WatchID, Title FROM hits_v1 WHERE WatchID = 9126318258181481721
    2020.03.26 17:01:02.785055 [ 73 ] {cd075c5e-45d8-4b64-bb99-fcc183c29b1c} <Debug> InterpreterSelectQuery: MergeTreeWhereOptimizer: condition "WatchID = 9126318258181481721" moved to PREWHERE
    2020.03.26 17:01:02.785603 [ 73 ] {cd075c5e-45d8-4b64-bb99-fcc183c29b1c} <Debug> tutorial.hits_v1 (SelectExecutor): Key condition: unknown
    ...
    2020.03.26 17:01:02.788193 [ 73 ] {cd075c5e-45d8-4b64-bb99-fcc183c29b1c} <Debug> executeQuery: Query pipeline:
    Union
     Expression × 20
      Expression
       MergeTreeThread
    
    

    日志在哪里:

    ---9-9---

    1. NULL值处理
    ClickHouse将NULL视为一个特殊的值进行聚合,即在聚合时列中的所有NULL值归为同一组。
    下面通过具体的示例演示NULL值的使用。
    准备数据:
    drop table t_null;
    create table t_null(key Nullable(UInt8), value UInt8) ENGINE=TinyLog;
    insert into t_null values
    (2, 1) (NULL, 2) (2, 3) (3,3) (NULL, 3);
    数据查看:
    SELECT * FROM t_null
    
    ┌──key─┬─value─┐
    │    2 │     1 │
    │ ᴺᵁᴸᴸ │     2 │
    │    2 │     3 │
    │    3 │     3 │
    │ ᴺᵁᴸᴸ │     3 │
    └──────┴───────┘
    基于key的sum聚合:
    SELECT key, sum(value) AS sum FROM t_null GROUP BY key;
    
    ┌──key─┬─sum─┐
    │    2 │   4 │
    │    3 │   3 │
    │ ᴺᵁᴸᴸ │   5 │
    └──────┴─────┘
    
    
    2. WITH TOTALS修饰符
    当指定WITH TOTALS修饰符,聚合查询将计算所有行的总计数。
    SELECT 
        UserID, 
        count(*) AS cnt
    FROM hits_v1
    GROUP BY UserID
        WITH TOTALS
    HAVING count() > 10
    LIMIT 3
    
    ┌──────────────UserID─┬─cnt─┐
    │  349463948327386591 │ 139 │
    │ 3479937375504503991 │ 145 │
    │ 3873537644544582407 │ 920 │
    └─────────────────────┴─────┘
    ​
    Extremes:
    ┌─UserID─┬─────cnt─┐
    │      0 │ 8640288 │
    └────────┴─────────┘
    
    
    
    3. WITH ROLLUP修饰符
    ROLLUP用于分组统计,用于计算每个分组以及上层分组的合计。
    构造数据:
    drop table t_rollup;
    create table t_rollup(prov String, city String, num UInt64) ENGINE=TinyLog;
    insert into t_rollup values
    ('anhui', 'tongling', 123) ('anhui', 'tongling', 100) ('anhui', 'tongling', 200)
    ('anhui', 'hefei', 100) ('anhui', 'tongling', 200) ('anhui', 'tongling', 300)
    ('jiangsu', 'nanjing', 10) ('jiangsu', 'nanjing', 20) ('jiangsu', 'nanjing', 30)
    ('jiangsu', 'suzhou', 5) ('jiangsu', 'suzhou', 10) ('jiangsu', 'suzhou', 15)
    ;
    查看数据:
    SELECT * FROM t_rollup ORDER BY prov, city;
    
    ┌─prov────┬─city─────┬─num─┐
    │ anhui   │ hefei    │ 100 │
    │ anhui   │ tongling │ 123 │
    │ anhui   │ tongling │ 100 │
    │ anhui   │ tongling │ 200 │
    │ anhui   │ tongling │ 200 │
    │ anhui   │ tongling │ 300 │
    │ jiangsu │ nanjing  │  10 │
    │ jiangsu │ nanjing  │  20 │
    │ jiangsu │ nanjing  │  30 │
    │ jiangsu │ suzhou   │   5 │
    │ jiangsu │ suzhou   │  10 │
    │ jiangsu │ suzhou   │  15 │
    └─────────┴──────────┴─────┘
    WITH ROLLUP聚合:
    SELECT prov, city, sum(num) AS sum FROM t_rollup GROUP BY prov, city WITH ROLLUP;
    
    ┌─prov────┬─city─────┬─sum─┐
    │ anhui   │ hefei    │ 100 │
    │ jiangsu │ nanjing  │  60 │
    │ jiangsu │ suzhou   │  30 │
    │ anhui   │ tongling │ 923 │
    └─────────┴──────────┴─────┘
    ┌─prov────┬─city─┬──sum─┐
    │ jiangsu │      │   90 │
    │ anhui   │      │ 1023 │
    └─────────┴──────┴──────┘
    ┌─prov─┬─city─┬──sum─┐
    │      │      │ 1113 │
    └──────┴──────┴──────┘
    上面的 ROLLUP类似于如下语句:
    SELECT prov, city, sum(num) AS sum FROM t_rollup GROUP BY prov, city
    UNION ALL
    SELECT prov, NULL, sum(num) AS sum FROM t_rollup GROUP BY prov, NULL
    UNION ALL
    SELECT NULL, NULL, sum(num) AS sum FROM t_rollup GROUP BY NULL, NULL;
    
    
    4. WITH CUBE修饰符
    CUBE翻译成中文是立方体,用于聚合统计时,表示每个维度之间自由组合计算聚合值。
    例如当需要对维度(A,B,C)计算CUBE的聚合,则会生成如下维度的组合:(A,B,C)、(A,B)、(A,C)、(B,C)、(A)、(B)、(C)和全表聚合。
    使用示例:
    SELECT prov, city, sum(num) AS sum FROM t_rollup GROUP BY prov, city WITH CUBE;
    
    ┌─prov────┬─city─────┬─sum─┐
    │ anhui   │ hefei    │ 100 │
    │ jiangsu │ nanjing  │  60 │
    │ jiangsu │ suzhou   │  30 │
    │ anhui   │ tongling │ 923 │
    └─────────┴──────────┴─────┘
    ┌─prov────┬─city─┬──sum─┐
    │ jiangsu │      │   90 │
    │ anhui   │      │ 1023 │
    └─────────┴──────┴──────┘
    ┌─prov─┬─city─────┬─sum─┐
    │      │ nanjing  │  60 │
    │      │ suzhou   │  30 │
    │      │ hefei    │ 100 │
    │      │ tongling │ 923 │
    └──────┴──────────┴─────┘
    ┌─prov─┬─city─┬──sum─┐
    │      │      │ 1113 │
    └──────┴──────┴──────┘

    文档:

    ---9-10---

    示例:
    生成测试数据:
    CREATE TABLE limit_by(id Int, val Int) ENGINE = Memory;
    INSERT INTO limit_by values(1, 10), (1, 11), (1, 12), (2, 20), (2, 21);
    查看表数据:
    SELECT * FROM limit_by
    
    ┌─id─┬─val─┐
    │  1 │  10 │
    │  1 │  11 │
    │  1 │  12 │
    │  2 │  20 │
    │  2 │  21 │
    └────┴─────┘
    LIMIT BY查询,从每个数据块的开头最多返回2行记录:
    SELECT * FROM limit_by ORDER BY id, val LIMIT 2 BY id;
    
    ┌─id─┬─val─┐
    │  1 │  10 │
    │  1 │  11 │
    │  2 │  20 │
    │  2 │  21 │
    └────┴─────┘
    LIMIT BY查询,从每个数据块的开头跳过1个数据块,最多返回2行记录:
    
    SELECT * FROM limit_by ORDER BY id, val LIMIT 1, 2 BY id;
    
    ┌─id─┬─val─┐
    │  1 │  11 │
    │  1 │  12 │
    │  2 │  21 │
    └────┴─────┘
    上面的语句,也可以改写为:
    SELECT
     * FROM limit_by ORDER BY id, val LIMIT 2 OFFSET 1 BY id;
    
    下面的查询返回每个domain和device_type的前5个referrer,最多返回100行:
    SELECT
        domainWithoutWWW(URL) AS domain,
        domainWithoutWWW(REFERRER_URL) AS referrer,
        device_type,
        count() cnt
    FROM hits
    GROUP BY domain, referrer, device_type
    ORDER BY cnt DESC
    LIMIT 5 BY domain, device_type
    LIMIT 100

    mysql的分页:https://blog.csdn.net/bandaoyu/article/details/89844673

    ---9-11---

    示例:
    生成测试数据:
    drop table t_order_by;
    create table t_order_by(x UInt8, y Nullable(Int64), factor UInt8, z Nullable(Float32)) ENGINE=TinyLog;
    
    insert into t_order_by values
    (1, null, 1, 3.2)
    (2, 2, 1,4.9)
    (3, 3, 1,2.3)
    (4, 0, 0,8.9)
    (5, 7, 1,10.2)
    (6, 6, 1,20.8)
    (7, 18, 1, null)
    (8, 0, 0, NAN)
    (9, null, 1, 28.1)
    (10, 29, 1, NAN)
    ;
    查看数据:
    SELECT * FROM t_order_by
    
    ┌──x─┬────y─┬─factor─┬────z─┐
    │  1 │ ᴺᵁᴸᴸ │      1 │  3.2 │
    │  2 │    2 │      1 │  4.9 │
    │  3 │    3 │      1 │  2.3 │
    │  4 │    0 │      0 │  8.9 │
    │  5 │    7 │      1 │ 10.2 │
    │  6 │    6 │      1 │ 20.8 │
    │  7 │   18 │      1 │ ᴺᵁᴸᴸ │
    │  8 │    0 │      0 │  nan │
    │  9 │ ᴺᵁᴸᴸ │      1 │ 28.1 │
    │ 10 │   29 │      1 │  nan │
    └────┴──────┴────────┴──────┘
    排序:
    SELECT y / factor AS r FROM t_order_by ORDER BY r ASC NULLS FIRST
    
    ┌────r─┐
    │ ᴺᵁᴸᴸ │
    │ ᴺᵁᴸᴸ │
    │  nan │
    │  nan │
    │    2 │
    │    3 │
    │    6 │
    │    7 │
    │   18 │
    │   29 │
    └──────┘
    SELECT y / factor AS r FROM t_order_by ORDER BY r ASC NULLS LAST
    
    ┌────r─┐
    │    2 │
    │    3 │
    │    6 │
    │    7 │
    │   18 │
    │   29 │
    │  nan │
    │  nan │
    │ ᴺᵁᴸᴸ │
    │ ᴺᵁᴸᴸ │
    └──────┘

    ---9-12---

    示例:
    创建测试数据:
    drop table col_names;
    CREATE TABLE col_names (aa Int8, ab Int8, bc Int) ENGINE = TinyLog;
    insert into col_names values (1,2,3);
    查询1:
    SELECT COLUMNS('a') FROM col_names
    
    ┌─aa─┬─ab─┐
    │  1 │  2 │
    └────┴────┘
    查询2:
    SELECT  COLUMNS('a'),  COLUMNS('b') FROM col_names
    
    ┌─aa─┬─ab─┬─ab─┬─bc─┐
    │  1 │  2 │  2 │  3 │
    └────┴────┴────┴────┘
    用于函数的查询:
    Note: 在toTypeName函数中应用COLUMNS('c'),此时COLUMNS('c')只能返回一列,否则会抛出异常。
    SELECT COLUMNS('a'), COLUMNS('c'), toTypeName(COLUMNS('c')) FROM col_names
    
    
    Note:COLUMNS('regexp')必须要匹配表中列,否则将抛出异常。
    SELECT COLUMNS('a1') FROM col_names
    
    Received exception from server (version 20.1.4):
    Code: 51. DB::Exception: Received from localhost:9001. DB::Exception: Empty list of columns in SELECT query. 

    ---9-13---

    下面通过示例说明DISTINCT与ORDER BY的执行顺序。
    生成测试数据:
    drop table t_distinct;
    create table t_distinct (x Int8, y Int8) ENGINE=TinyLog;
    insert into t_distinct values (1, 1) (2, 2) (3, 3) (2, 4);
    查看数据:
    SELECT * FROM t_distinct
    
    ┌─x─┬─y─┐
    │ 1 │ 1 │
    │ 2 │ 2 │
    │ 3 │ 3 │
    │ 2 │ 4 │
    └───┴───┘
    
    1  1
    2  2
    3  3
    
    3
    2
    1
    
    
    使用ORDER BY的去重:
    SELECT DISTINCT x FROM t_distinct ORDER BY y DESC
    
    ┌─x─┐
    │ 3 │
    │ 2 │
    │ 1 │
    └───┘
    
    
    我们通过反证法说明ORDER BY和DISTINCT的执行顺序:
    如果ORDER BY先执行,则排序后的数据如下:
    ┌─x─┬─y─┐
    │ 2 │ 4 │
    │ 3 │ 3 │
    │ 2 │ 2 │
    │ 1 │ 1 │
    └───┴───┘
    然后针对x列去重:
    ┌─x─┬─y─┐
    │ 2 │ 4 │
    │ 3 │ 3 │
    │ 1 │ 1 │
    └───┴───┘
    选择x列:
    ┌─x─┬
    │ 2 │
    │ 3 │
    │ 1 │
    └───┴
    这个分析结果跟我们实际上我们通过DITINCT去重后的结果不一致。
    
    
    
    

    ---9-14---

    ---9-15---

    示例:
    drop table t_users_1;
    drop table t_users_2;
    create table t_users_1(id String, name String, age UInt8) ENGINE=Log;
    create table t_users_2(user_id String, user_name String, age Nullable(UInt8)) ENGINE=Log;
    
    insert into t_users_1 values('id001', 'xiaohe', 11);
    
    insert into t_users_2 values('id001', 'xiaohe', 11) ('id002', 'xiaojiang', 22);
    
    查看数据:
    SELECT * FROM t_users_1
    ┌─id────┬─name───┬─age─┐
    │ id001 │ xiaohe │  11 │
    └───────┴────────┴─────┘
    ​
    --------------------------------------------
    ​
    SELECT * FROM t_users_2
    ┌─user_id─┬─user_name─┬─age─┐
    │ id001   │ xiaohe    │  11 │
    │ id002   │ xiaojiang │  22 │
    └─────────┴───────────┴─────┘
    使用UNION ALL查询:
    SELECT id, name, age FROM t_users_1
    UNION ALL
    SELECT user_id, user_name, age FROM t_users_2
    ;
    
    ┌─id────┬─name──────┬─age─┐
    │ id001 │ xiaohe    │  11 │
    │ id002 │ xiaojiang │  22 │
    └───────┴───────────┴─────┘
    ┌─id────┬─name───┬─age─┐
    │ id001 │ xiaohe │  11 │
    └───────┴────────┴─────┘
    
    
    
    
    
    

    ---9-16---

    例子没看

    ---9-17---

    创建测试数据:
    drop table hits_test;
    create table hits_test(UserID String, EventDate Date) ENGINE=Log;
    
    
    insert into hits_test values
    ('id001', '2020-03-27')
    ('id002', '2020-03-27')
    ('id001', '2020-03-27')
    ('id003', '2020-03-27')
    ('id001', '2020-03-28')
    ('id002', '2020-03-28')
    ('id003', '2020-03-28')
    ('id001', '2020-03-28')
    ('id002', '2020-03-28')
    ('id003', '2020-03-28')
    ('id004', '2020-03-28')
    ('id005', '2020-03-28')
    ('id004', '2020-03-28')
    ('id006', '2020-03-28')
    ('id002', '2020-03-29')
    ('id003', '2020-03-29')
    ('id003', '2020-03-29')
    ('id001', '2020-03-29')
    ('id002', '2020-03-29')
    ('id005', '2020-03-29')
    ('id007', '2020-03-29')
    ;
    查看数据:
    SELECT * FROM hits_test
    
    ┌─UserID─┬──EventDate─┐
    │ id001  │ 2020-03-27 │
    │ id002  │ 2020-03-27 │
    │ id001  │ 2020-03-27 │
    │ id003  │ 2020-03-27 │
    │ id001  │ 2020-03-28 │
    │ id002  │ 2020-03-28 │
    │ id003  │ 2020-03-28 │
    │ id001  │ 2020-03-28 │
    │ id002  │ 2020-03-28 │
    │ id003  │ 2020-03-28 │
    │ id004  │ 2020-03-28 │
    │ id005  │ 2020-03-28 │
    │ id004  │ 2020-03-28 │
    │ id006  │ 2020-03-28 │
    │ id002  │ 2020-03-29 │
    │ id003  │ 2020-03-29 │
    │ id003  │ 2020-03-29 │
    │ id001  │ 2020-03-29 │
    │ id002  │ 2020-03-29 │
    │ id005  │ 2020-03-29 │
    │ id007  │ 2020-03-29 │
    └────────┴────────────┘
    
    在2020-03-27访问过网站的用户,统计他们在每天的网站浏览量占比。
    SELECT 
        EventDate, 
        avg(UserID IN 
        (
            SELECT UserID
            FROM hits_test
            WHERE EventDate = toDate('2020-03-27')
        )) AS ratio
    FROM hits_test
    GROUP BY EventDate
    ORDER BY EventDate ASC;
    
    
    ┌──EventDate─┬──────────────ratio─┐
    │ 2020-03-27 │                  1 │
    │ 2020-03-28 │                0.6 │
    │ 2020-03-29 │ 0.7142857142857143 │
    └────────────┴────────────────────┘
    
    
    2. NULL处理
    
    
    drop table t_null;
    create table t_null(x UInt8, y Nullable(UInt8)) ENGINE=Log;
    insert into t_null values(1, NULL) (2, 3);
    
    查看数据:
    SELECT * FROM t_null;
    
    ┌─x─┬────y─┐
    │ 1 │ ᴺᵁᴸᴸ │
    │ 2 │    3 │
    └───┴──────┘
    IN操作的查询:
    SELECT * FROM t_null WHERE y IN (NULL, 3);
    
    ┌─x─┬─y─┐
    │ 2 │ 3 │
    └───┴───┘
    所有与NULL运算的结果返回false。

    ---9-18---

    1. Tuple相关操作
    
    测试数据:
    drop table t_tuple;
    create table t_tuple(id String, addr Tuple(UInt16,String,String)) ENGINE=TinyLog;
    insert into t_tuple values('id001', tuple(556, 'anhui', 'anqing'));
    select * from t_tuple;
    
    select id, addr.1, addr.2 from t_tuple;
    
    ┌─id────┬─tupleElement(addr, 1)─┬─tupleElement(addr, 2)─┐
    │ id001 │                   556 │ anhui                 │
    └───────┴───────────────────────┴───────────────────────┘
    ​
    
    select id, tupleElement(addr, 1) as area_code from t_tuple;
    ┌─id────┬─area_code─┐
    │ id001 │       556 │
    └───────┴───────────┘
    
    2. 数组相关操作
    测试数据:
    drop table t_arr;
    create table t_arr(id String, hobby Array(String)) ENGINE=TinyLog;
    insert into t_arr values('id001', ['football', 'basketball', 'movie']);
    insert into t_arr values('id001', ['eat', 'sleep', 'play', 'ride']);
    select * from t_arr;
    数组和元组的元素的 索引都是从1开始的。a[N]和函数arrayElement(a, N)的使用。
    xiaochen :) select id, hobby[1] as first_hobby from t_arr;
    
    ┌─id────┬─first_hobby─┐
    │ id001 │ football    │
    │ id001 │ eat         │
    └───────┴─────────────┘
    ​
    xiaochen :) select id, arrayElement(hobby,1) as first_hobby from t_arr;
    
    ┌─id────┬─first_hobby─┐
    │ id001 │ football    │
    │ id001 │ eat         │
    └───────┴─────────────┘
    
    
    3. 负数
    select -2 as a, negate (2) as b;
    ┌──a─┬──b─┐
    │ -2 │ -2 │
    └────┴────┘
    
    4 比较操作符
    (1)、相等
    a = b 
    a == b
    等价函数:equals(a, b)
    
    (2)不相等
    a != b
    a <> b
    等价函数:notEquals(a, b)
    
    (3)、不等比较
    a <= b, 等价函数:lessOrEquals(a, b)
    a >= b , 等价函数:greaterOrEquals(a, b)
    a < b , 等价函数:less(a, b)
    a > b , 等价函数:greater(a, b)
    
    (4)、like匹配
    
    a LIKE s, 等价函数:like(a, b)
    a NOT LIKE s, 等价函数:notLike(a, b)
    
    (5)、区间比较
    a BETWEEN b AND c, 等价于: a >= b AND a <= c
    a NOT BETWEEN b AND c , 等价于:a < b OR a > c 。
    
    5. 数据集操作符
    a IN ... : 等价函数 in(a, b)。
    a NOT IN ... : 等价函数 notIn(a, b)。
    a GLOBAL IN ... : 等价函数 globalIn(a, b)。
    a GLOBAL NOT IN ... : 等价函数 globalNotIn(a, b)。
    
    6. 时间操作之EXTRACT
    从给定的日期提取一个时间片段, 支持Date和DateTime数据类型。例如可以从给定的日期检索月或者秒等。
    使用toYear、toMonth等也可实现类似功能。
    
    EXTRACT(part FROM date);
    part参数指定要解析的时间片段名称, 可选的片段名称如下:
    DAY — 月份的日,Possible  valaues: 1–31.
    MONTH — 月份, Possible values: 1–12.
    YEAR — 年.
    SECOND —秒. Possible values: 0–59.
    MINUTE — 分钟. Possible values: 0–59.
    HOUR — 小时. Possible values: 0–23.
    
    SELECT EXTRACT(DAY FROM toDate('2017-06-15'));
    SELECT EXTRACT(MONTH FROM toDate('2017-06-15'));
    SELECT EXTRACT(YEAR FROM toDate('2017-06-15'));
    
    CREATE TABLE test.Orders
    (
        OrderId UInt64,
        OrderName String,
        OrderDate DateTime
    )
    ENGINE = Log;
    
    INSERT INTO test.Orders VALUES (1, 'Jarlsberg Cheese', toDateTime('2008-10-11 13:23:44'));
    
    SELECT
        toYear(OrderDate) AS OrderYear,
        toMonth(OrderDate) AS OrderMonth,
        toDayOfMonth(OrderDate) AS OrderDay,
        toHour(OrderDate) AS OrderHour,
        toMinute(OrderDate) AS OrderMinute,
        toSecond(OrderDate) AS OrderSecond
    FROM test.Orders;
    
    ┌─OrderYear─┬─OrderMonth─┬─OrderDay─┬─OrderHour─┬─OrderMinute─┬─OrderSecond─┐
    │      2008 │         10 │       11 │        13 │          23 │          44 │
    └───────────┴────────────┴──────────┴───────────┴─────────────┴─────────────┘
    
    
    7. 时间操作之INTERVAL
    在Date和DateTime数据类型的值使用Interval类型的值做算术运算操作。
    Interval类型: - SECOND - MINUTE - HOUR - DAY - WEEK - MONTH - QUARTER - YEAR 。
    不同类型的interval不能合并。例如不能使用表达式:"INTERVAL 4 DAY 1 HOUR"。 
    示例:
    SELECT now() AS current_date_time, current_date_time + INTERVAL 4 DAY + INTERVAL 3 HOUR
    ┌───current_date_time─┬─plus(plus(now(), toIntervalDay(4)), toIntervalHour(3))─┐
    │ 2020-03-21 12:08:50 │                                    2020-03-25 15:08:50 │
    └─────────────────────┴────────────────────────────────────────────────────────┘
    
    8. 逻辑运算
    逻辑非:NOT a ,等价于not(a) 。
    逻辑与:a AND b, 等价于and(a, b)。
    逻辑或: a OR b, 等价于or(a, b) 。
    
    9. 三目运算符
    元算法:
    a ? b : c
    等价函数:  if(a, b, c)
     如果b或C是arrayJoin()函数,则无论“ a”条件如何,都将复制每一行。
    select 1 as a, a>1?'a>1':'a<=1' as rs ;
    ┌─a─┬─rs───┐
    │ 1 │ a<=1 │
    └───┴──────┘
    
    select 2 as a, a>1?'a>1':'a<=1' as rs ;
    ┌─a─┬─rs──┐
    │ 2 │ a>1 │
    └───┴─────┘
    
    10. case when 表达式
    CASE [x]
        WHEN a THEN b
        [WHEN ... THEN ...]
        [ELSE c]
    END
    
    
    SELECT case number when 3 then 111 when 5 then 222 when 7 then 333 else number end as new_number FROM system.numbers LIMIT 10;
    ┌─new_number─┐
    │          0 │
    │          1 │
    │          2 │
    │        111 │
    │          4 │
    │        222 │
    │          6 │
    │        333 │
    │          8 │
    │          9 │
    └────────────┘
    
    
    11. 创建数组和元组
    数组 [x1, ...]  等价函数: array(x1, ...)
    元组 (x1, x2, ...)  等价函数: tuple(x2, x2, ...)
    
    select (1,1,2);
    select [1,2];
    
    13. NULL判断
    支持两种操作符: IS NULL 或 IS NOT NULL 。
    (1)、IS NULL
    对于 Nullable类型的值, 返回0或1。
    
    (2)、IS NOT NULL
    对于 Nullable类型的值, 返回0或1。
    
    SELECT * FROM t_null WHERE y IS NOT NULL
    
    13. 连接运算符
    s1 || s2 等价函数: concat(s1, s2)
    select 'id001'||':'||'football';
    ┌─concat('id001', ':', 'football')─┐
    │ id001:football                   │
    └──────────────────────────────────┘
    
    
    
    

    ---9-19---

    展开全文
  • clickhouse与mysql的整合。 没看完。 ---7-2--- ---7-4---

    clickhouse与mysql的整合。

    没看完。

    ---7-2---

     

    ---7-4---

    展开全文
  • clickhouse教程-01-02-03

    千次阅读 2020-10-09 08:38:29
    clickhouse官网:https://clickhouse.tech/#quick-start 下载四个rpm包: ---2-1-2-2--- ---2-3---

    资料:

    分片是一个数据节点,副本是集群的架构,存储的数据是一样的。

    特点,仅仅支持有限的delete和update功能:

    修改和删除的操作是有限的,仅仅适合在大量的这样的操作下才会生效,并且是异步执行的。

    ---1---

    clickhouse官网:https://clickhouse.tech/#quick-start

    https://packagecloud.io/altinity/clickhouse

    安装:按照这个可以安装成功。

    https://blog.csdn.net/jorondo/article/details/105605415?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-1-105605415.nonecase&utm_term=%E7%A6%BB%E7%BA%BF%E5%AE%89%E8%A3%85clickhouse&spm=1000.2123.3001.4430

    下载四个rpm包:

    yum安装:

    yum install *.rpm

    启动clickhouse:

    systemctl start clickhouse-server

    查看状态:

    systemctl status clickhouse-server

    clickhouse交互:

    clickhouse-client

    我的clickhouse安装在了changgou这个服务器,并且安装包和数据也是在这个服务器上的。

    安装包在这里,版本和书本上的一致。

    目前131这个机器上也有了。

    简单语句:

    1. 安装文件清单
    clickhouse-client-${version}.noarch.rpm
    clickhouse-common-static-dbg-${version}.x86_64.rpm
    clickhouse-common-static-${version}.x86_64.rpm
    clickhouse-server-${version}.noarch.rpm
    
    2. 安装命令  
    
    命令1: rpm -ivh *.rpm
    
    命令2: yum install *.rpm
    
    3. 卸载
    查看
    rpm -qa | grep clickhouse
    卸载命令:
    rmp -e  rpm包名
    
    4. 启动/关闭服务
    systemctl start clickhouse-server
    systemctl status clickhouse-server
    systemctl restart clickhouse-server
    
    5. 交互式命令
    clickhouse-client
    
    select 1
    
    1. 测试数据
    https://clickhouse-datasets.s3.yandex.net/hits/tsv/hits_v1.tsv.xz
    https://clickhouse-datasets.s3.yandex.net/visits/tsv/visits_v1.tsv.xz
    
    xz -d hits_v1.tsv.xz
    xz -d visits_v1.tsv.xz
    
    yum install xz 
    
    2. 创建数据库
    clickhouse-client --query "CREATE DATABASE IF NOT EXISTS tutorial"
    
    3. 建表
    hits_v1
    
    clickhouse-client  -m //-m是指的是可以换行建表的
    
    CREATE TABLE tutorial.hits_v1
    (
        `WatchID` UInt64,
        `JavaEnable` UInt8,
        `Title` String,
        `GoodEvent` Int16,
        `EventTime` DateTime,
        `EventDate` Date,
        `CounterID` UInt32,
        `ClientIP` UInt32,
        `ClientIP6` FixedString(16),
        `RegionID` UInt32,
        `UserID` UInt64,
        `CounterClass` Int8,
        `OS` UInt8,
        `UserAgent` UInt8,
        `URL` String,
        `Referer` String,
        `URLDomain` String,
        `RefererDomain` String,
        `Refresh` UInt8,
        `IsRobot` UInt8,
        `RefererCategories` Array(UInt16),
        `URLCategories` Array(UInt16),
        `URLRegions` Array(UInt32),
        `RefererRegions` Array(UInt32),
        `ResolutionWidth` UInt16,
        `ResolutionHeight` UInt16,
        `ResolutionDepth` UInt8,
        `FlashMajor` UInt8,
        `FlashMinor` UInt8,
        `FlashMinor2` String,
        `NetMajor` UInt8,
        `NetMinor` UInt8,
        `UserAgentMajor` UInt16,
        `UserAgentMinor` FixedString(2),
        `CookieEnable` UInt8,
        `JavascriptEnable` UInt8,
        `IsMobile` UInt8,
        `MobilePhone` UInt8,
        `MobilePhoneModel` String,
        `Params` String,
        `IPNetworkID` UInt32,
        `TraficSourceID` Int8,
        `SearchEngineID` UInt16,
        `SearchPhrase` String,
        `AdvEngineID` UInt8,
        `IsArtifical` UInt8,
        `WindowClientWidth` UInt16,
        `WindowClientHeight` UInt16,
        `ClientTimeZone` Int16,
        `ClientEventTime` DateTime,
        `SilverlightVersion1` UInt8,
        `SilverlightVersion2` UInt8,
        `SilverlightVersion3` UInt32,
        `SilverlightVersion4` UInt16,
        `PageCharset` String,
        `CodeVersion` UInt32,
        `IsLink` UInt8,
        `IsDownload` UInt8,
        `IsNotBounce` UInt8,
        `FUniqID` UInt64,
        `HID` UInt32,
        `IsOldCounter` UInt8,
        `IsEvent` UInt8,
        `IsParameter` UInt8,
        `DontCountHits` UInt8,
        `WithHash` UInt8,
        `HitColor` FixedString(1),
        `UTCEventTime` DateTime,
        `Age` UInt8,
        `Sex` UInt8,
        `Income` UInt8,
        `Interests` UInt16,
        `Robotness` UInt8,
        `GeneralInterests` Array(UInt16),
        `RemoteIP` UInt32,
        `RemoteIP6` FixedString(16),
        `WindowName` Int32,
        `OpenerName` Int32,
        `HistoryLength` Int16,
        `BrowserLanguage` FixedString(2),
        `BrowserCountry` FixedString(2),
        `SocialNetwork` String,
        `SocialAction` String,
        `HTTPError` UInt16,
        `SendTiming` Int32,
        `DNSTiming` Int32,
        `ConnectTiming` Int32,
        `ResponseStartTiming` Int32,
        `ResponseEndTiming` Int32,
        `FetchTiming` Int32,
        `RedirectTiming` Int32,
        `DOMInteractiveTiming` Int32,
        `DOMContentLoadedTiming` Int32,
        `DOMCompleteTiming` Int32,
        `LoadEventStartTiming` Int32,
        `LoadEventEndTiming` Int32,
        `NSToDOMContentLoadedTiming` Int32,
        `FirstPaintTiming` Int32,
        `RedirectCount` Int8,
        `SocialSourceNetworkID` UInt8,
        `SocialSourcePage` String,
        `ParamPrice` Int64,
        `ParamOrderID` String,
        `ParamCurrency` FixedString(3),
        `ParamCurrencyID` UInt16,
        `GoalsReached` Array(UInt32),
        `OpenstatServiceName` String,
        `OpenstatCampaignID` String,
        `OpenstatAdID` String,
        `OpenstatSourceID` String,
        `UTMSource` String,
        `UTMMedium` String,
        `UTMCampaign` String,
        `UTMContent` String,
        `UTMTerm` String,
        `FromTag` String,
        `HasGCLID` UInt8,
        `RefererHash` UInt64,
        `URLHash` UInt64,
        `CLID` UInt32,
        `YCLID` UInt64,
        `ShareService` String,
        `ShareURL` String,
        `ShareTitle` String,
        `ParsedParams` Nested(
            Key1 String,
            Key2 String,
            Key3 String,
            Key4 String,
            Key5 String,
            ValueDouble Float64),
        `IslandID` FixedString(16),
        `RequestNum` UInt32,
        `RequestTry` UInt8
    )
    ENGINE = MergeTree()
    PARTITION BY toYYYYMM(EventDate)
    ORDER BY (CounterID, EventDate, intHash32(UserID))
    SAMPLE BY intHash32(UserID)
    SETTINGS index_granularity = 8192;
    
    
    
    
    CREATE TABLE tutorial.visits_v1
    (
        `CounterID` UInt32,
        `StartDate` Date,
        `Sign` Int8,
        `IsNew` UInt8,
        `VisitID` UInt64,
        `UserID` UInt64,
        `StartTime` DateTime,
        `Duration` UInt32,
        `UTCStartTime` DateTime,
        `PageViews` Int32,
        `Hits` Int32,
        `IsBounce` UInt8,
        `Referer` String,
        `StartURL` String,
        `RefererDomain` String,
        `StartURLDomain` String,
        `EndURL` String,
        `LinkURL` String,
        `IsDownload` UInt8,
        `TraficSourceID` Int8,
        `SearchEngineID` UInt16,
        `SearchPhrase` String,
        `AdvEngineID` UInt8,
        `PlaceID` Int32,
        `RefererCategories` Array(UInt16),
        `URLCategories` Array(UInt16),
        `URLRegions` Array(UInt32),
        `RefererRegions` Array(UInt32),
        `IsYandex` UInt8,
        `GoalReachesDepth` Int32,
        `GoalReachesURL` Int32,
        `GoalReachesAny` Int32,
        `SocialSourceNetworkID` UInt8,
        `SocialSourcePage` String,
        `MobilePhoneModel` String,
        `ClientEventTime` DateTime,
        `RegionID` UInt32,
        `ClientIP` UInt32,
        `ClientIP6` FixedString(16),
        `RemoteIP` UInt32,
        `RemoteIP6` FixedString(16),
        `IPNetworkID` UInt32,
        `SilverlightVersion3` UInt32,
        `CodeVersion` UInt32,
        `ResolutionWidth` UInt16,
        `ResolutionHeight` UInt16,
        `UserAgentMajor` UInt16,
        `UserAgentMinor` UInt16,
        `WindowClientWidth` UInt16,
        `WindowClientHeight` UInt16,
        `SilverlightVersion2` UInt8,
        `SilverlightVersion4` UInt16,
        `FlashVersion3` UInt16,
        `FlashVersion4` UInt16,
        `ClientTimeZone` Int16,
        `OS` UInt8,
        `UserAgent` UInt8,
        `ResolutionDepth` UInt8,
        `FlashMajor` UInt8,
        `FlashMinor` UInt8,
        `NetMajor` UInt8,
        `NetMinor` UInt8,
        `MobilePhone` UInt8,
        `SilverlightVersion1` UInt8,
        `Age` UInt8,
        `Sex` UInt8,
        `Income` UInt8,
        `JavaEnable` UInt8,
        `CookieEnable` UInt8,
        `JavascriptEnable` UInt8,
        `IsMobile` UInt8,
        `BrowserLanguage` UInt16,
        `BrowserCountry` UInt16,
        `Interests` UInt16,
        `Robotness` UInt8,
        `GeneralInterests` Array(UInt16),
        `Params` Array(String),
        `Goals` Nested(
            ID UInt32,
            Serial UInt32,
            EventTime DateTime,
            Price Int64,
            OrderID String,
            CurrencyID UInt32),
        `WatchIDs` Array(UInt64),
        `ParamSumPrice` Int64,
        `ParamCurrency` FixedString(3),
        `ParamCurrencyID` UInt16,
        `ClickLogID` UInt64,
        `ClickEventID` Int32,
        `ClickGoodEvent` Int32,
        `ClickEventTime` DateTime,
        `ClickPriorityID` Int32,
        `ClickPhraseID` Int32,
        `ClickPageID` Int32,
        `ClickPlaceID` Int32,
        `ClickTypeID` Int32,
        `ClickResourceID` Int32,
        `ClickCost` UInt32,
        `ClickClientIP` UInt32,
        `ClickDomainID` UInt32,
        `ClickURL` String,
        `ClickAttempt` UInt8,
        `ClickOrderID` UInt32,
        `ClickBannerID` UInt32,
        `ClickMarketCategoryID` UInt32,
        `ClickMarketPP` UInt32,
        `ClickMarketCategoryName` String,
        `ClickMarketPPName` String,
        `ClickAWAPSCampaignName` String,
        `ClickPageName` String,
        `ClickTargetType` UInt16,
        `ClickTargetPhraseID` UInt64,
        `ClickContextType` UInt8,
        `ClickSelectType` Int8,
        `ClickOptions` String,
        `ClickGroupBannerID` Int32,
        `OpenstatServiceName` String,
        `OpenstatCampaignID` String,
        `OpenstatAdID` String,
        `OpenstatSourceID` String,
        `UTMSource` String,
        `UTMMedium` String,
        `UTMCampaign` String,
        `UTMContent` String,
        `UTMTerm` String,
        `FromTag` String,
        `HasGCLID` UInt8,
        `FirstVisit` DateTime,
        `PredLastVisit` Date,
        `LastVisit` Date,
        `TotalVisits` UInt32,
        `TraficSource` Nested(
            ID Int8,
            SearchEngineID UInt16,
            AdvEngineID UInt8,
            PlaceID UInt16,
            SocialSourceNetworkID UInt8,
            Domain String,
            SearchPhrase String,
            SocialSourcePage String),
        `Attendance` FixedString(16),
        `CLID` UInt32,
        `YCLID` UInt64,
        `NormalizedRefererHash` UInt64,
        `SearchPhraseHash` UInt64,
        `RefererDomainHash` UInt64,
        `NormalizedStartURLHash` UInt64,
        `StartURLDomainHash` UInt64,
        `NormalizedEndURLHash` UInt64,
        `TopLevelDomain` UInt64,
        `URLScheme` UInt64,
        `OpenstatServiceNameHash` UInt64,
        `OpenstatCampaignIDHash` UInt64,
        `OpenstatAdIDHash` UInt64,
        `OpenstatSourceIDHash` UInt64,
        `UTMSourceHash` UInt64,
        `UTMMediumHash` UInt64,
        `UTMCampaignHash` UInt64,
        `UTMContentHash` UInt64,
        `UTMTermHash` UInt64,
        `FromHash` UInt64,
        `WebVisorEnabled` UInt8,
        `WebVisorActivity` UInt32,
        `ParsedParams` Nested(
            Key1 String,
            Key2 String,
            Key3 String,
            Key4 String,
            Key5 String,
            ValueDouble Float64),
        `Market` Nested(
            Type UInt8,
            GoalID UInt32,
            OrderID String,
            OrderPrice Int64,
            PP UInt32,
            DirectPlaceID UInt32,
            DirectOrderID UInt32,
            DirectBannerID UInt32,
            GoodID String,
            GoodName String,
            GoodQuantity Int32,
            GoodPrice Int64),
        `IslandID` FixedString(16)
    )
    ENGINE = CollapsingMergeTree(Sign)
    PARTITION BY toYYYYMM(StartDate)
    ORDER BY (CounterID, StartDate, intHash32(UserID), VisitID)
    SAMPLE BY intHash32(UserID)
    SETTINGS index_granularity = 8192
    
    
    4. 数据导入
    
    date
    clickhouse-client --query "INSERT INTO tutorial.hits_v1 FORMAT TSV" --max_insert_block_size=100000 < hits_v1.tsv
    date
    
    clickhouse-client --query "INSERT INTO tutorial.visits_v1 FORMAT TSV" --max_insert_block_size=100000 < visits_v1.tsv
    
    select * from hits_v1 limit 1; \G
    
    5. 查询
    SELECT
        StartURL AS URL,
        AVG(Duration) AS AvgDuration
    FROM tutorial.visits_v1
    WHERE StartDate BETWEEN '2014-03-23' AND '2014-03-30'
    GROUP BY URL
    ORDER BY AvgDuration DESC
    LIMIT 10;
    
    
    SELECT
        sum(Sign) AS visits,
        sumIf(Sign, has(Goals.ID, 1105530)) AS goal_visits,
        (100. * goal_visits) / visits AS goal_percent
    FROM tutorial.visits_v1
    WHERE (CounterID = 912887) AND (toYYYYMM(StartDate) = 201403) AND (domain(StartURL) = 'yandex.ru');
    
    
    
    =========================================================================================
    clickhouse-client
    交互式模式:clickhouse-client
    非交互式模式: 指定了--query参数或将数据发送至标准的stdin。
    
    测试表创建:
    create database if not exists test;
    use test;
    drop table test;
    create table test(id UInt8, text String, created DateTime) ENGINE=TinyLog;
    
    
    批模式数据导入:
    echo -ne "1, 'some text', '2016-08-14 00:00:00'\n2, 'some more text', '2016-08-14 00:00:01'" | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
    
    cat <<_EOF | clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV";
    3, 'some text', '2016-08-14 00:00:00'
    4, 'some more text', '2016-08-14 00:00:01'
    _EOF
    
    数据导出
    Clickhouse-client --query="select * from test.test" > file.tsv
    Cat file.tsv
    
    select * from test.test;\G
    
    总结:
    (1)、批模式下的默认数据格式为TabSeparated,可使用FORMAT指定格式。
    (2)、使用--multiquery参数,可同时执行多个查询(除了INSERT),每个查询语句使用分号(;)分隔。
    (3)、使用--multiline或-m参数,允许执行多行的查询。
    (4)、在查询语句的分号之后指定\G或使用\G替换分号, 数据以垂直的格式展示。
    (5)、历史的执行语句保存在操作系统文件:~/.clickhouse-client-history。
    (6)、退出客户端的方式,按Ctrl + D或Ctrl + C,或执行命令:exit、quit、logout、q、Q、:q。
    
    
    查询中指定参数:
    clickhouse-client --param_myid=3 --database=test --query="select * from test where id>{myid:UInt8}"
    clickhouse-client --database=test --query="select * from test where id>3"
    查询语句指定参数,参数值通过客户端参数传递。
    使用大括号占位要传递的参数值,格式为: {<name>:<data type>}
    name:占位标识符。通过clickhouse-client参数指定,格式为--param_<name> = value 。
    data type:指定参数值的数据类型,例如:UInt8、String等。
    
    clickhouse-client --param_parName="[1, 2]"  -q "SELECT * FROM table WHERE a = {parName:Array(UInt16)}"
    
    clickhouse-client --query="select * from test.test FORMAT TabSeparated" > file.tsv
    
    clickhouse-client查找配置文件的顺序:
    (1)、通过--config-file指定的配置文件。
    (2)、./clickhouse-client.xml
    (3)、~/.clickhouse-client/config.xml
    (4)、/etc/clickhouse-client/config.xml
    
     {host}
     {port}
     {user}
     {database}
     {display_name}
     
     
     =========================================================================================================================
     MySQL接口操作ClickHouse
     1. 安装MySQL的客户端
     tar -xzf MySQL-client-5.6.38-1.el6.x86_64.tar.gz
     rpm -ivh MySQL-client-5.6.38-1.el6.x86_64.rpm
     
     2. 配置MySQL协议
      vim /etc/clickhouse-server/config.xml
      <mysql_port>9004</mysql_port>
    
    命令行连接到ClickHouse:
    mysql --protocol tcp -u default -P 9004
    
    
    为了兼容所有MySQL客户端,建议使用SHA1加密用户密码:
    PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD"  \
    | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
    
    w+YuQ0p3
    8879bd5e440c57cf4be5f9188a4b46779c96a322
    
    
    配置文件:
    vim /etc/clickhouse-server/users.xml
    <password_double_sha1_hex>8879bd5e440c57cf4be5f9188a4b46779c96a322</password_double_sha1_hex>
    
    执行命令:
    mysql --protocol tcp -u default -P 9004 --password=w+YuQ0p3
    
    
    
    ---------------------------
    DBeaver可视化工具安装与使用
    
    
    配置参数:
    timeout
    socket_timeout
    
    
    外部聚合,如果用于聚合内存不足,10G
    max_bytes_before_external_group_by=5G
    
    
    1. 安装DBeaver
    2. 下载DBeaver的JDBC驱动
    3. 连接ClickHouse, 注意,配置CH的网络
    /etc/clickhouse-server/config.xml
    <listen_host>0.0.0.0</listen_host>
    4. 设置参数
    在URL模板中,设置ClickHouse的参数
    jdbc:clickhouse://{host}:{port}[/{database}]?socket_timeout=600000&max_bytes_before_external_group_by=20000000

    问题:clickhouse的批量数据导入。

    ---2-1-2-2-2-3-2-4---

    TabSeparated模式:

    数据格式,注意那个箭头:

    语句:

    导入数据,如何操作:

    总结:

    TabSeparated、TabSeparatedRaw、TabSeparatedWithNames和TabSeparatedWithNamesAndTypes
    
    1. TabSeparated
    数据按行写入,tab制表符分隔。使用严格Unix命令行。
    注意:最后一行必须包含换行符。
    默认格式。
    简写:TSV
    数据插入和数据查询时,均可使用。
    
    
    CREATE TABLE tsv_demo(srcip String, destip String, time String) ENGINE = TinyLog;
    
    
    
    
    clickhouse-client --query "INSERT INTO tsv_demo FORMAT TabSeparated/TSV" --max_insert_block_size=100000 < tsv_demo.tsv 
    
    Code: 117. DB::Exception: 
    You have carriage return (\r, 0x0D, ASCII 13) at end of first row.
    It's like your input data has DOS/Windows style line separators, that are illegal in TabSeparated format. You must transform your file to Unix format.
    But if you really need carriage return at end of string value of last column, you need to escape it as \r.
    
    这是由于windows使用\r\n表示回车换行, 在linux中使用\n表示换行。 因此,需要将\r给去掉。
    
    
    转换为UNIX格式:
    dos2unix tsv_demo.tsv
    
    输出格式:
    select * from tsv_demo FORMAT TSV;
    
    2. TabSeparatedRaw
    
    简称:TSVRaw
    TabSeparatedRaw格式不会对行数据进行转义, 即不会将换行、制表符等转换为转义字符。
    只能在数据查询的时候使用。
    
    
    zhangsan	nanjing\tjiangsu	23	From nanjing
    lisi	hangzhou\tzhejiang	32	\x41 amazing place
    xiaoming	hefei\tanhui	25	notepad
    
    建表语句:
    create table escape_demo(name String, addr String, age UInt8, desc String) ENGINE=TinyLog;
    
    
    select * from escape_demo FORMAT TSV;
    
    zhangsan	nanjing\tjiangsu	23	From nanjing
    lisi	hangzhou\tzhejiang	32	A amazing place
    xiaoming	hefei\tanhui	25	notepad
    
    3 rows in set. Elapsed: 0.005 sec.
    
    
    
    SELECT *
    FROM escape_demo
    FORMAT TabSeparatedRaw
    
    zhangsan	nanjing	jiangsu	23	From nanjing
    lisi	hangzhou	zhejiang	32	A amazing place
    xiaoming	hefei	anhui	25	notepad
    
    3 rows in set. Elapsed: 0.005 sec
    
    3. TabSeparatedWithNames
     在查询时,TabSeparatedWithNames格式的第一行显示列的名称
     在数据导入时,第一行完全被忽略,不会解析第一行为表头。
     简称:TSVWithNames
     在数据查询和数据导入均可使用。
     
     数据导入:
     clickhouse-client --query="INSERT INTO escape_demo FORMAT TSVWithNames" < escape_demo.tsv
    
    数据查询:
    select * from escape_demo FORMAT TSVWithNames;
    
    4. TabSeparatedWithNamesAndTypes
    在查询时,TabSeparatedWithNamesAndTypes格式在主数据的前面额外显示两行数据,第一行显示列的名称, 第二行显示列的数据类型。
    在数据导入时,前面两行的数据完全被忽略。
    简写:TSVWithNamesAndTypes
    在数据导入和查询时均可使用。

    ---3-1---

    暂时不看了

    ---3-2-3-7---

    展开全文
  • MergeTree我们是用的最多的。 ---4-1--- 建表模版: 看下下面的关键字: 看下行为的额外参数: 看下系统表: --- 我们来建两张表: 没指定主键,默认情况下主键和排序键是一样的...其他....切片表..
  • ClickHouse系列教程

    万次阅读 2019-07-08 19:50:49
    ClickHouse系列教程一:Debian/Ubuntu 下ClickHouse的安装和使用 ClickHouse系列教程二:使用航班飞行数据 ClickHouse系列教程三:MergeTree引擎分析 ClickHouse系列教程四:允许远程连接 allow remote access ...
  • ClickHouse 极简教程

    2021-06-13 11:37:53
    ClickHouse 简介 Yandex开源的数据分析的数据库,名字叫做ClickHouse,适合流式或批次入库的时序数据。ClickHouse不应该被用作通用数据库,而是作为超高性能的海量数据快速查询的分布式实时处理平台,在数据...
  • ClickHouse基础教程.docx

    2020-04-28 17:45:40
    教程主要内容包括列式数据仓库Clickhouse的简介,基于CentOS本地自建Clickhouse,分为单机模式和集群模式,Clickhouse支持的数据类型,表引擎以及Clickhouse的SQL语法,适用于Clickhouse初学者快速入门
  • ClickHouse入门教程

    2020-11-01 19:02:26
    ClickHouse简介 ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。ClickHouse最初是一款名为Yandex.Metrica的产品,主要用于WEB流量分析。ClickHouse的全称是Click Stream,Data WareHouse,简称...
  • clickhouse基础教程

    2021-05-06 10:42:12
    Clickhouse由俄罗斯Yandex公司开源的数据库,专为OLAP而设计。 Yandex是俄罗斯最大的搜索引擎公司,官方宣称ClickHouse 日处理记录数”十亿级”。 发布之初跑分要超过很多流行的商业MPP数据库软件,对标老东家HP的...
  • ClickHouse学习教程

    千次阅读 2020-06-11 21:31:54
    学习资料参考 GitHub clickhouse-doc-zh china 数据目录 由浅入深系列 阿里云clickhouse optional book ClickHouse原理解析与应用实践 个人 朱凯 altinity 官网 clickhouse-operator Altinity是国外一家从事...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 696
精华内容 278
关键字:

clickhouse教程