
# ClickHouse数据库应用开发
在ClickHouse的使用过程中，由于使用不规范的方式访问和查询，导致业务失败的情况时有发生。此外，偶尔也会发生因为网络闪断等导致连接和查询失败的情况。
MRS提供了ClickHouse的样例代码工程，旨在提供连接重试机制和规范化用户连接和查询的方法，从而减少业务失败的风险，提升系统的稳定性和可靠性。
本样例代码工程包含了连接、查询和插入相关规则和建议，以及相关的代码示例，可以帮助客户更好地理解和实践这些方法。通过使用本代码样例，客户可以有效地降低业务失败的概率，提升用户体验和业务质量。
#### 操作步骤
1. 先获取clickhouse-example样例代码工程。 
   代码获取地址：<https://github.com/huaweicloud/huaweicloud-mrs-example/blob/mrs-3.1.2/src/clickhouse-examples/>。
   
   
2. 在样例工程"conf"目录下有一个"clickhouse-example.properties"配置文件，其中各项的配置的作用如下所示： 
   ```
   #连接节点或Balancer的ip列表，ip之间用逗号隔开
   loadBalancerIPList=
   #是否需要开启ssl,如果取值为true，则loadBalancerHttpsPort必填
   sslUsed=true
   #端口号
   loadBalancerHttpPort=
   loadBalancerHttpsPort=
   #ClickHouse安全模式开关，安全模式集群时该参数固定为true。
   CLICKHOUSE_SECURITY_ENABLED=true
   #连接的用户名
   user=
   #连接的用户的密码
   password=
   #集群名称
   clusterName=
   #数据库名称
   databaseName=
   #表名称
   tableName=
   #一个批次写入的条数
   batchRows=10000
   #写入数据的总批次
   batchNum=10
   #ip:port。安全模式下https端口，普通模式下http端口
   clickhouse_dataSource_ip_list=
   #ip:tcp port
   native_dataSource_ip_list=ip:port,ip:port,ip:port
   ```
   
   
3. 在Demo.java有三种连接JDBC的样例：节点的JDBC连接、balancer的JDBC连接和TCP端口的balancer的JDBC连接。
4. Demo提供了createDatabase、createTable、insertData和queryData的样例。
 
#### 规则
- 大批量少频次的插入。 内容要求：ClickHouse的每次数据插入都会生成一到多个part文件，如果data part过多则会导致merge压力变大，甚至出现服务异常影响数据插入。建议一次插入10万行，每秒不超过1次插入。
  
- 低频次执行DDL语句。 内容要求：ClickHouse实例会串行执行DDL语句，当出现节点负载过高、故障等场景时，可能造成DDL语句执行失败和堆积，导致集群元数据和数据不一致。
  
- 一次只插入一个分区内的数据。 内容要求：如果数据属于不同的分区，则每次插入，不同分区的数据会独立生成part文件，导致part总数量膨胀。甚至写入报错"Merges are processing significantly slower than inserts"。一批次写入的数据，对应的分区数太多。ClickHouse建表之后insert batch时，会对不同的分区创建一个目录。如果一个batch里面的数据对应了过多的分区，那么一次insert就会生成较多的分区目录，后台merge线程处理速度跟不上分区增加的速度，社区规格是每秒不超过一个数据目录。
  具体的操作：确认一个batch的数据对应了多少个分区，insert的时候，尽量保证一个batch包含的分区数是1。
  
- 慎用delete、update操作。 内容要求：建议使用CollapsingMergeTree、VersionedCollapsingMergeTree引擎或根据分区批量清理。
  
- ClickHouse需要写本地表。 内容要求：连接balancer写入报错Request Entity Too Large。这是由于Nginx对http请求体大小有限制，而一次写入的数据量超过了这个限制。
  规避：修改Nginx配置项client_max_body_size为一个较大的值。
  解决：写本地表，不要通过balancer写入数据。
  
- 禁用实验特性 内容要求：ClickHouse实验特性可能存在设计或功能缺陷，不具备商用能力。如果在生产环境上使用实验特性，会给生产环境带来数据准确性、集群稳定性等多个方面的系统风险。
  
- JDBC攒批入库禁用函数 内容要求：使用jdbc攒批方式写数据到ClickHouse，对ClickHouse函数（例如：时间函数now()）会解析成String类型，而数据库里是**DateTime**类型，导致类型不匹配，数据入库异常。
  解决：在代码中生成时间，并生成字段传入或者在ClickHouse中修改表结构，给对应字段默认值。
  
 
#### 建议
- 建议客户端不要安装在ClickHouse Server节点，避免使用客户端给ClickHouse Server节点带来额外的资源占用。
- 查询增加重试机制 clickhouse-example.properties的配置文件的loadBalancerIPList可以配置多个ip，在二次样例代码中已经实现从第一个ip开始连接查询，查询失败时，继续连接下一个ip进行查询。
  
 
- 每个应用配置的loadBalancerIPList顺序不要一致，以免对balancer ip产生访问热点 例如应用一配置loadBalancerIPList=ip1，ip2，ip3，应用二配置loadBalancerIPList=ip3，ip1，ip2。
  
- 根据连接方式选择端口 普通集群默认开启8123端口，安全集群默认开启8443端口。
  端口号查看方式：在集群的Manager界面选择"集群 \> 服务 \> ClickHouse \> 配置"。
  - 用于通过HTTP连接到ClickHouse server的端口默认为8123。
  
  - 用于通过HTTPS连接到ClickHouse server的端口默认为8443。
  
  - 用户客户端通过TCP连接到ClickHouse server的端口默认为9000。
  
  - 用户客户端通过TCP ssl连接到ClickHouse server的端口默认为9440。
  
  - ClickHouseBalancer的HTTP端口默认为21425。
  
  - ClickHouseBalancer的HTTPS端口默认为21426。
   
 
