为什么要使用ClickHouse

在项目立项之初,对于数据仓库这块的建设,其实有很多的技术选择,根据官方对比数据显示,100M数据集的跑分结果:ClickHouse比Vertia快约5倍,比Hive快279倍,比My SQL 快801倍。Vertia是商业软件,收费且不开源,小公司搞不起;Hive依赖于hadoop生态圈的,成本太高,甲方不太愿意提供那么多服务器,也不愿意虚拟化服务器,且虚拟化后的性能会进一步衰弱;mysql就不用考虑了,大量数据的存储只能靠分库分表,复杂且麻烦。我相信这些是大部分小公司都会面临的问题,总之一句话就是成本太高,承受不起。
另外,我还做过文档型数据库elasticsearch的调研,通过对比,如果数据是放到了buff/cache中,那么elasticsearch的查询速度和ClickHouse是一样的,但是如果没有存放,那么Clickhouse查询效率则比elasticsearch快50倍。且elasticsearch作为文档型数据库,在做数据展示的时候,会随着数据的不断深入,而变得越来越慢,因为文档型数据库就像翻书一样,查询数据是一页一页的往后,所以速度越来越慢。
clickhouse的出现,从一定意义上是补全了hadoop实时性的短板,其实它们对数据的处理有很多相同的地方,比如压缩存储、资源分配、数据分区,只是hadoop更擅长离线处理,而clickhouse是实时处理。hadoop中的hbase也是一种列式数据库,从操作上来说,我感觉它更像是一种nosql数据库,无论是从使用成本、学习成本、运维成本,都远远高于clickhouse。

那么基于以上原因,最终我将数据仓库组件选为ClickHouse。

用clickhouse做什么事情

项目背景:项目由设备和平台组成,设备负责采集日志,生成数据;平台负责接收数据、分析数据、统计数据、展示数据。
clickhouse能为我们做这些工作:

  1. 数据存储,按每天的数据分片存储,定期自动删除
  2. 快速查询数据,实时展示
  3. 秒级统计,可实时聚合计算,响应结果展示
  4. 节约大量的硬件成本,数据采用高效压缩,顺序IO

安装部署

  1. 检查一下是否支持SSE 4.2指令集
    grep -q sse4_2 /proc/cpuinfo && echo “SSE 4.2 supported” || echo “SSE 4.2 not supported”
  2. 上传最新版的clickhouse安装包
  3. 开始安装
    yum install -y ODBC libicu.x86_64
    rpm -Uvh clickhouse-*.rpm --nodeps --force
  4. 设置默认账号密码和只读密码
    vi /etc/clickhouse-server/users.xml
    参照如下配置
<yandex>
		    <profiles>
			<default>
			    <max_memory_usage>10000000000</max_memory_usage>
			    <use_uncompressed_cache>0</use_uncompressed_cache>
			    <load_balancing>random</load_balancing>
			</default>
			<readonly>
			    <max_memory_usage>10000000000</max_memory_usage>
			    <use_uncompressed_cache>0</use_uncompressed_cache>
			    <load_balancing>random</load_balancing>
			    <readonly>1</readonly>
			</readonly>
		    </profiles>
		    <quotas>
			<!-- Name of quota. -->
			<default>
			    <interval>
				<duration>3600</duration>
				<queries>0</queries>
				<errors>0</errors>
				<result_rows>0</result_rows>
				<read_rows>0</read_rows>
				<execution_time>0</execution_time>
			    </interval>
			</default>
		    </quotas>
		    <users>
			<default>
			    <password_sha256_hex>967f3bf355dddfabfca1c9f5cab39352b2ec1cd0b05f9e1e6b8f629705fe7d6e</password_sha256_hex>
			    <networks incl="networks" replace="replace">
				<ip>::/0</ip>
			    </networks>
			    <profile>default</profile>
			    <quota>default</quota>
			</default>
			<ck>
			    <password_sha256_hex>967f3bf355dddfabfca1c9f5cab39352b2ec1cd0b05f9e1e6b8f629705fe7d6e</password_sha256_hex>
			    <networks incl="networks" replace="replace">
				<ip>::/0</ip>
			    </networks>
			    <profile>readonly</profile>
			    <quota>default</quota>
			</ck>
		    </users>
		</yandex>
密码生成方式:
	PASSWORD=$(base64 < /dev/urandom | head -c8);  # 获取一个随机密码,也可以直接指定
	echo "$PASSWORD"; 
	echo -n "$PASSWORD" | sha256sum | tr -d '-'
	出现如下
	oM9HOLs5     -- 密码
	d741aef7b31900eddd525dd588a7e0e2761d5f231a588f36eff9d1090d83392b   --密文
  1. 设置数据目录
    vi /etc/clickhouse-server/config.xml
    /data/clickhouse/
    <tmp_path>/data/clickhouse/tmp/</tmp_path>
  2. 允许远程登录
    vi /etc/clickhouse-server/config.xml
    取消注释:"<listen_host>::</listen_host>"
  3. 启动|停止
    service clickhouse-server stop
    service clickhouse-server start
  4. 可视化界面tabix
    vi /etc/clickhouse-server/config.xml
    取消注释:
<http_server_default_response><![CDATA[<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http    ://loader.tabix.io/master.js"></script></body></html>]]></http_server_default_response>
service clickhouse-server restart

以上clickhouse服务端和客户端就已经安装启动好了,下面就进行实际操作吧。

开始实战

  1. 创建数据库和表结构
    ##登录clickhouse数据库,默认用户名default,密码为abcds,-m表示多行输入,输入回车不执行,遇到分号执行
    clickhouse-client --password=abcds -m
    ##创建aa数据库
    create database aa;
    ##创建表结构
    CREATE TABLE aa.equipment_info_test (id String, mac String, device_business_type String, create_time String, create_date String) ENGINE = MergeTree() PARTITION BY device_business_type ORDER BY device_business_type SETTINGS index_granularity = 8192;
  2. 创建一个spring-boot程序
  3. 增加如下配置
  4. hive和clickhouse区别 clickhouse与hive_hive和clickhouse区别

  5. 加载数据源
package com.nsac.clickhouse.config;

import lombok.Getter;
import lombok.Setter;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "spring.datasource.click")
@Getter
@Setter
public class JdbcParamConfig {
	private String driverClassName;
	private String url;
	private Integer initialSize;
	private Integer maxActive;
	private Integer minIdle;
	private Integer maxWait;
	private String username;
	private String password;
}
package com.nsac.clickhouse.config;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
public class DruidConfig {
	@Resource
	private JdbcParamConfig jdbcParamConfig;

	@Bean
	public DataSource dataSource() {
		DruidDataSource datasource = new DruidDataSource();
		datasource.setUrl(jdbcParamConfig.getUrl());
		datasource.setDriverClassName(jdbcParamConfig.getDriverClassName());
		datasource.setInitialSize(jdbcParamConfig.getInitialSize());
		datasource.setMinIdle(jdbcParamConfig.getMinIdle());
		datasource.setMaxActive(jdbcParamConfig.getMaxActive());
		datasource.setMaxWait(jdbcParamConfig.getMaxWait());
		datasource.setUsername(jdbcParamConfig.getUsername());
		datasource.setPassword(jdbcParamConfig.getPassword());
		return datasource;
	}
}
  1. 编写mybatis 配置文件
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper SYSTEM "http://mybatis.org/dtd/mybatis-3-mapper.dtd" PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN">

-<mapper namespace="com.nsac.clickhouse.dao.TestSQLDao">

<select resultType="java.util.Map" parameterType="String" id="excuteSQL">select count(*) from equipment_info_test eq </select>


-<insert parameterType="java.util.List" id="insertSQL" useGeneratedKeys="false">
insert into equipment_info_test (id, mac, device_business_type,create_time,create_date) values 
<foreach separator="," index="index" item="item" collection="list">(#{item.id},#{item.mac, jdbcType=VARCHAR},#{item.deviceBusinessType},#{item.createTime, jdbcType=VARCHAR},#{item.createDate, jdbcType=VARCHAR}) </foreach>

</insert>

</mapper>
  1. 编写DAO层
package com.nsac.clickhouse.dao;

import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

@Repository
public interface TestSQLDao {

	List<Map<String, Object>> excuteSQL(String sql);
	
	void insertSQL(List<Map<String, Object>> list);

}
  1. 接下来就可以编写service、controller层了,在使用上与mysql这种关系型数据库是没有任何区别的,所以,对于java程序猿来说,学习使用clickhouse成本为0,直接就可以上手操作。