1.建表语句

  1. -- 建表
  2. CREATE TABLE IF NOT EXISTS tb_stat ( id String, region String, group String, yesterday INT, today INT, stat_date DateTime ) ENGINE = SummingMergeTree PARTITION BY ( toYYYYMM ( stat_date ), region ) ORDER BY ( toStartOfHour ( stat_date ), region, group );
  3. -- 数据
  4. INSERT INTO tb_stat VALUES( '1','1232364', '111', 32, 2, '2021-07-09 12:56:00' );
  5. INSERT INTO tb_stat VALUES( '2','1232364', '111', 34, 44, '2021-07-09 12:21:00' );
  6. INSERT INTO tb_stat VALUES( '3','1232364', '111', 54, 12, '2021-07-09 12:20:00' );
  7. INSERT INTO tb_stat VALUES( '4','1232364', '222', 45, 11, '2021-07-09 12:13:00' );
  8. INSERT INTO tb_stat VALUES( '5','1232364', '222', 32, 33, '2021-07-09 12:44:00' );
  9. INSERT INTO tb_stat VALUES( '6','1232364', '222', 12, 23, '2021-07-09 12:22:00' );
  10. INSERT INTO tb_stat VALUES( '7','1232364', '333', 54, 54, '2021-07-09 12:11:00' );
  11. INSERT INTO tb_stat VALUES( '8','1232364', '333', 22, 74, '2021-07-09 12:55:00' );
  12. INSERT INTO tb_stat VALUES( '9','1232364', '333', 12, 15, '2021-07-09 12:34:00' );

2.依赖

这里只粘贴相关依赖:

  1. <!-- https://mvnrepository.com/artifact/ru.yandex.clickhouse/clickhouse-jdbc -->
  2. <dependency>
  3. <groupId>ru.yandex.clickhouse</groupId>
  4. <artifactId>clickhouse-jdbc</artifactId>
  5. <version>0.2.4</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
  8. <dependency>
  9. <groupId>com.alibaba</groupId>
  10. <artifactId>druid</artifactId>
  11. <version>1.1.21</version>
  12. </dependency>
  13. <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
  14. <dependency>
  15. <groupId>com.baomidou</groupId>
  16. <artifactId>mybatis-plus-boot-starter</artifactId>
  17. <version>3.3.2</version>
  18. </dependency>

3.配置

application.yml 配置:SpringBoot默认是不注入 clickhouse 属性值的,需要自己绑定。

  1. server:
  2. port: 8080
  3. spring:
  4. datasource:
  5. # 数据源选择
  6. type: com.alibaba.druid.pool.DruidDataSource
  7. # clickhouse配置
  8. click:
  9. driverClassName: ru.yandex.clickhouse.ClickHouseDriver
  10. url: jdbc:clickhouse://172.81.205.216:8123/default
  11. username: default
  12. password:
  13. initialSize: 10
  14. maxActive: 100
  15. minIdle: 10
  16. maxWait: 6000

Bean配置:用了druid监控所以在这里边初始化了,这个 DataSource 也可以在启动类里初始化。

  1. @Configuration
  2. public class DruidConfig {
  3. @Bean
  4. @ConfigurationProperties(prefix = "spring.datasource.click")
  5. public DataSource druidDataSource() {
  6. return new DruidDataSource();
  7. }
  8. }
  9. // 或者用
  10. @SpringBootApplication
  11. @MapperScan(value = "com.example.demo.**.mapper")
  12. public class DemoApplication {
  13. public static void main(String[] args) {
  14. SpringApplication.run(DemoApplication.class, args);
  15. }
  16. @Bean
  17. @ConfigurationProperties(prefix = "spring.datasource.click")
  18. public DataSource druidDataSource() {
  19. return new DruidDataSource();
  20. }
  21. }

3.使用

尝试使用mybatis-plus-generator代码生成报错:

  1. DB::Exception: Syntax error: failed at position 6 ('table') (line 1, col 6): table status WHERE 1=1 AND NAME IN ('tb_stat')

所以entity、mapper、service、controller使用的是其他库表生成的代码然后修改的。这里只贴出重要的类:
entity代码: statDate字段要使用@JsonFormat格式化日期字符串。

  1. @Data
  2. @EqualsAndHashCode(callSuper = false)
  3. @Accessors(chain = true)
  4. @TableName(value = "tb_stat")
  5. @ApiModel(value = "Stat对象", description = "")
  6. public class Stat implements Serializable {
  7. private static final long serialVersionUID = 1L;
  8. @ApiModelProperty(value = "ID")
  9. private String id;
  10. @ApiModelProperty(value = "区域")
  11. private String region;
  12. @ApiModelProperty(value = "分组")
  13. private String group;
  14. @ApiModelProperty(value = "昨天")
  15. private Integer yesterday;
  16. @ApiModelProperty(value = "今天")
  17. private Integer today;
  18. @ApiModelProperty(value = "时间")
  19. @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
  20. private Date statDate;
  21. }

controller代码:

  1. @RestController
  2. @RequestMapping("/stat")
  3. public class StatController {
  4. @Autowired
  5. private IStatService statService;
  6. @PostMapping("/add")
  7. public boolean addStat(@RequestBody Stat stat) {
  8. return statService.save(stat);
  9. }
  10. @GetMapping("/del/{id}")
  11. public boolean delStatById(@PathVariable String id) {
  12. return statService.removeById(id);
  13. }
  14. @PostMapping("/update")
  15. public boolean updateStat(@RequestBody Stat stat) {
  16. return statService.updateById(stat);
  17. }
  18. @PostMapping("/list")
  19. public List<Stat> getStatList() {
  20. LambdaQueryWrapper<Stat> query = Wrappers.lambdaQuery(Stat.class);
  21. return statService.list(query);
  22. }
  23. }

测试结果说明:
添加和查询可以正藏使用mybatis-plus的api,删除和更新时会报错:

  1. // 这个是删除的报错
  2. DB::Exception: Syntax error: failed at position 1 ('DELETE'):
  3. DELETE FROM tb_stat WHERE id='10'.
  4. // 这个是更新的报错
  5. DB::Exception: Syntax error: failed at position 1 ('UPDATE') (line 1, col 1):
  6. UPDATE tb_stat SET region='222',group='222',yesterday=222,today=222,stat_date='2020-03-25 12:13:00' WHERE id='4'.

报错的原因说明:
clickhouse 数据库的语法有一些不同:

  1. -- 删除语法
  2. alter table tb_stat delete WHERE id='10';
  3. -- 修改语法
  4. alter table tb_stat update today=222 WHERE id='4';

所以删除和修改的SQL要自己在xml文件内写。

4.clickhouse应用场景(copy):

1.绝大多数请求都是用于读访问的
2.数据需要以大批次(大于1000行)进行更新,而不是单行更新;或者根本没有更新操作
3.数据只是添加到数据库,没有必要修改
4.读取数据时,会从数据库中提取出大量的行,但只用到一小部分列
5.表很“宽”,即表中包含大量的列
6.查询频率相对较低(通常每台服务器每秒查询数百次或更少)
7.对于简单查询,允许大约50毫秒的延迟
8.列的值是比较小的数值和短字符串(例如,每个URL只有60个字节)
9.在处理单个查询时需要高吞吐量(每台服务器每秒高达数十亿行)
10.不需要事务
11.数据一致性要求较低
12.每次查询中只会查询一个大表。除了一个大表,其余都是小表
13.查询结果显著小于数据源。即数据有过滤或聚合。返回结果不超过单个服务器内存大小

5.总结

SpringBoot 集成 clickhouse 并使用持久层框架mybatis-plus还是比较容易的,但是 clickhouse 数据库的语法有所不同,mybatis-plus的部分api无法使用需要自己书写。