JDBC 驱动程序
clickhouse-jdbc
使用最新的 java 客户端 实现了标准 JDBC 接口。如果性能/直接访问至关重要,我们建议直接使用最新的 java 客户端 。
如果您正在查找早期版本的 JDBC 驱动程序文档,请参阅此处。
0.7.x 的更改
在 0.8 版本中,我们尝试使驱动程序更严格地遵循 JDBC 规范,因此删除了一些可能影响您的功能
旧功能 | 注释 |
---|---|
事务支持 | 早期版本的驱动程序仅模拟事务支持,这可能会导致意外结果。 |
响应列重命名 | ResultSet 是可变的 - 为了效率起见,它们现在是只读的 |
多语句 SQL | 多语句支持仅是模拟的,现在它严格遵循 1:1 |
命名参数 | 不是 JDBC 规范的一部分 |
基于流的 PreparedStatement | 早期版本的驱动程序允许非 jdbc 用法 PreparedStatement - 如果您需要此类选项,我们建议您查看 Java 客户端 及其 示例。 |
Date
在存储时没有时区,而 DateTime
在存储时带有时区。如果您不小心,这可能会导致意外结果。
环境要求
- OpenJDK 版本 >= 8
设置
- Maven
- Gradle (Kotlin)
- Gradle
<!-- https://mvnrepository.com/artifact/com.clickhouse/clickhouse-jdbc -->
<dependency>
<groupId>com.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.8.0</version>
<classifier>shaded-all</classifier>
</dependency>
// https://mvnrepository.com/artifact/com.clickhouse/clickhouse-jdbc
implementation("com.clickhouse:clickhouse-jdbc:0.8.0:shaded-all")
// https://mvnrepository.com/artifact/com.clickhouse/clickhouse-jdbc
implementation 'com.clickhouse:clickhouse-jdbc:0.8.0:shaded-all'
配置
驱动程序类: com.clickhouse.jdbc.ClickHouseDriver
URL 语法: jdbc:(ch|clickhouse)[:<protocol>]://endpoint1[,endpoint2,...][/<database>][?param1=value1¶m2=value2][#tag1,tag2,...]
,例如
jdbc:clickhouse:https://127.0.0.1:8123
jdbc:clickhouse:https://127.0.0.1:8443?ssl=true
连接属性:
除了标准的 JDBC 属性外,驱动程序还支持底层 java 客户端 提供的 ClickHouse 特定属性。如果功能不受支持,可能的方法将返回 SQLFeatureNotSupportedException
。其他自定义属性包括
属性 | 默认值 | 描述 |
---|---|---|
disable_frameworks_detection | true | 禁用 User-Agent 的框架检测 |
jdbc_ignore_unsupported_values | false | 抑制 SQLFeatureNotSupportedException |
clickhouse.jdbc.v1 | false | 使用旧的 JDBC 实现而不是新的 JDBC |
default_query_settings | null | 允许通过查询操作传递默认查询设置 |
支持的数据类型
JDBC 驱动程序支持与底层 java 客户端 相同的数据格式。
处理日期、时间和时区
java.sql.Date
、 java.sql.Time
和 java.sql.Timestamp
可能会使时区的计算变得复杂 - 虽然它们当然受支持,但您可能需要考虑使用 java.time 包。 ZonedDateTime
和 OffsetDateTime
都是 java.sql.Timestamp、 java.sql.Date 和 java.sql.Time 的绝佳替代品。
创建连接
String url = "jdbc:ch://my-server:8123/system";
Properties properties = new Properties();
DataSource dataSource = new DataSource(url, properties);//DataSource or DriverManager are the main entry points
try (Connection conn = dataSource.getConnection()) {
... // do something with the connection
提供凭据和设置
String url = "jdbc:ch://127.0.0.1:8123?jdbc_ignore_unsupported_values=true&socket_timeout=10";
Properties info = new Properties();
info.put("user", "default");
info.put("password", "password");
info.put("database", "some_db");
//Creating a connection with DataSource
DataSource dataSource = new DataSource(url, info);
try (Connection conn = dataSource.getConnection()) {
... // do something with the connection
}
//Alternate approach using the DriverManager
try (Connection conn = DriverManager.getConnection(url, info)) {
... // do something with the connection
}
简单语句
try (Connection conn = dataSource.getConnection(...);
Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("select * from numbers(50000)");
while(rs.next()) {
// ...
}
}
插入
try (PreparedStatement ps = conn.prepareStatement("INSERT INTO mytable VALUES (?, ?)")) {
ps.setString(1, "test"); // id
ps.setObject(2, LocalDateTime.now()); // timestamp
ps.addBatch();
...
ps.executeBatch(); // stream everything on-hand into ClickHouse
}
HikariCP
// connection pooling won't help much in terms of performance,
// because the underlying implementation has its own pool.
// for example: HttpURLConnection has a pool for sockets
HikariConfig poolConfig = new HikariConfig();
poolConfig.setConnectionTimeout(5000L);
poolConfig.setMaximumPoolSize(20);
poolConfig.setMaxLifetime(300_000L);
poolConfig.setDataSource(new ClickHouseDataSource(url, properties));
try (HikariDataSource ds = new HikariDataSource(poolConfig);
Connection conn = ds.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery("SELECT * FROM system.numbers LIMIT 3")) {
while (rs.next()) {
// handle row
log.info("Integer: {}, String: {}", rs.getInt(1), rs.getString(1));//Same column but different types
}
}
更多信息
有关更多信息,请参阅我们的 GitHub 存储库 和 Java 客户端文档。
故障排除
日志记录
驱动程序使用 slf4j 进行日志记录,并将使用 classpath
上的第一个可用实现。
解决大型插入的 JDBC 超时问题
当在 ClickHouse 中执行具有较长执行时间的大型插入时,您可能会遇到类似以下的 JDBC 超时错误
Caused by: java.sql.SQLException: Read timed out, server myHostname [uri=https://hostname.aws.clickhouse.cloud:8443]
这些错误可能会中断数据插入过程并影响系统稳定性。要解决此问题,您可能需要在客户端的操作系统中调整一些超时设置。
Mac OS
在 Mac OS 上,可以调整以下设置来解决此问题
net.inet.tcp.keepidle
: 60000net.inet.tcp.keepintvl
: 45000net.inet.tcp.keepinit
: 45000net.inet.tcp.keepcnt
: 8net.inet.tcp.always_keepalive
: 1
Linux
在 Linux 上,仅等效设置可能无法解决问题。由于 Linux 处理套接字保持活动设置的方式存在差异,因此需要额外的步骤。请按照以下步骤操作
-
在
/etc/sysctl.conf
或相关配置文件中调整以下 Linux 内核参数net.inet.tcp.keepidle
: 60000net.inet.tcp.keepintvl
: 45000net.inet.tcp.keepinit
: 45000net.inet.tcp.keepcnt
: 8net.inet.tcp.always_keepalive
: 1net.ipv4.tcp_keepalive_intvl
: 75net.ipv4.tcp_keepalive_probes
: 9net.ipv4.tcp_keepalive_time
:60(您可以考虑将此值从默认的 300 秒降低)
-
修改内核参数后,运行以下命令应用更改
sudo sysctl -p
设置这些设置后,您需要确保客户端在套接字上启用了保持活动选项
properties.setProperty("socket_keepalive", "true");