JDBC 驱动
clickhouse-jdbc 使用最新的 Java 客户端实现了标准 JDBC 接口。
如果性能或直接访问至关重要,建议直接使用最新的 Java 客户端。
环境要求
- OpenJDK 8 或更高版本
设置
- Maven
- Gradle(Kotlin)
- Gradle
配置
驱动程序类: com.clickhouse.jdbc.ClickHouseDriver
com.clickhouse.jdbc.ClickHouseDriver 是新旧 JDBC 实现的外观类,默认使用新的 JDBC 实现。
如需使用旧的 JDBC 实现,可在连接属性中将 clickhouse.jdbc.v1 属性设置为 true。
com.clickhouse.jdbc.Driver 是新版 JDBC 实现。
com.clickhouse.jdbc.DriverV1 是旧版 JDBC 实现。
URL 语法: jdbc:(ch|clickhouse)[:<protocol>]://endpoint[:port][/<database>][?param1=value1¶m2=value2][#tag1,tag2,...],例如:
jdbc:clickhouse:http://localhost:8123jdbc:clickhouse:https://localhost:8443?ssl=true
关于 URL 语法,有以下几点需要注意:
- URL 中只能包含一个 endpoint
- 当使用的协议不是默认的 'HTTP' 时,必须显式指定协议
- 如果端口号不是默认的 '8123',则需要显式指定。
- 驱动程序不会根据端口推断协议,你需要显式指定协议
- 当已指定协议时,无需设置
ssl参数。
连接属性
主要配置参数在 java client 中定义。这些参数应按原样传递给驱动程序。驱动程序还有一些自有属性,它们不属于客户端配置的一部分,具体列举如下。
驱动属性:
| 属性 | 默认值 | 描述 |
|---|---|---|
disable_frameworks_detection | true | 禁用基于 User-Agent 的框架检测 |
jdbc_ignore_unsupported_values | false | 在不影响驱动程序正常工作的情况下忽略 SQLFeatureNotSupportedException |
clickhouse.jdbc.v1 | false | 使用旧版 JDBC 实现,而不是新版 JDBC 实现 |
default_query_settings | null | 允许在查询中传递默认查询设置 |
jdbc_resultset_auto_close | true | 当关闭 Statement 时自动关闭 ResultSet |
beta.row_binary_for_simple_insert | false | 使用基于 RowBinary 写入器的 PreparedStatement 实现。仅适用于 INSERT INTO ... VALUES 类型的查询。 |
jdbc_resultset_auto_close | true | 在关闭 Statement 时自动关闭 ResultSet |
jdbc_use_max_result_rows | false | 启用后,将使用服务器属性 max_result_rows 来限制查询返回的行数,并覆盖用户设置的溢出模式。有关详细信息,请参见 JavaDoc。 |
jdbc_sql_parser | JAVACC | 配置要使用的 SQL 解析器。可选值:ANTLR4、ANTLR4_PARAMS_PARSER、JAVACC。 |
配置示例:
这等同于以下 JDBC URL:
注意:无需对 JDBC URL 或属性进行 URL 编码,系统将自动进行编码。
支持的数据类型
JDBC 驱动支持与底层 Java 客户端相同的数据格式。
处理日期、时间和时区
java.sql.Date、java.sql.Time 和 java.sql.Timestamp 可能会使时区计算变得复杂——尽管它们当然是受支持的,
您可以考虑使用 java.time 包。ZonedDateTime 和
OffsetDateTime 都是 java.sql.Timestamp、java.sql.Date 和 java.sql.Time 的理想替代方案。
Date 存储时不包含时区信息,而 DateTime 存储时包含时区信息。如果不注意这一点,可能会导致意外结果。
创建连接
提供凭据和配置
简单语句
插入
HikariCP
更多信息
如需了解更多信息,请参阅我们的 GitHub 仓库 和 Java 客户端文档。
故障排除
日志
该驱动使用 slf4j 进行日志记录,并将使用 classpath 中首个可用的实现。
解决大批量插入时的 JDBC 超时问题
在 ClickHouse 中执行耗时较长的大批量插入操作时,可能会遇到如下 JDBC 超时错误:
这些错误可能会中断数据插入过程并影响系统稳定性。要解决此问题,您可能需要调整客户端操作系统中的若干超时设置。
macOS
在 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 处理套接字 keep-alive 设置的方式不同,需要执行额外的步骤。请按照以下步骤操作:
- 在
/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 秒降低)
- 修改内核参数后,运行以下命令使更改生效:
设置这些配置后,您需要确保客户端在套接字上启用 Keep-Alive 选项:
迁移指南
主要变更
| 功能 | V1(旧版) | V2(新版) |
|---|---|---|
| 事务支持 | 部分支持 | 不支持 |
| 响应结果列重命名 | 部分支持 | 不支持 |
| 多语句 SQL | 不支持 | 不允许 |
| 命名参数 | 支持 | 不支持(JDBC 规范未定义) |
使用 PreparedStatement 进行流式数据传输 | 支持 | 不支持 |
- JDBC V2 采用了更加轻量级的实现,因此移除了一些功能。
- JDBC V2 不支持流式数据,因为流式数据并不在 JDBC 规范或 Java 的支持范围内。
- JDBC V2 需要显式配置。不提供故障转移的默认设置。
- 协议必须在 URL 中显式指定,不应依赖端口号进行隐式协议推断。
配置更改
仅有两个枚举值:
com.clickhouse.jdbc.DriverProperties- 驱动程序自身的配置属性。com.clickhouse.client.api.ClientConfigProperties- 客户端配置属性。有关客户端配置更改的说明,请参见 Java Client 文档。
连接属性的解析方式如下:
- 会优先从 URL 解析属性,这些属性将覆盖所有其他属性。
- 驱动属性不会传递到客户端。
- 端点(主机、端口、协议)从 URL 中解析。
示例:
数据类型变更
| ClickHouse 类型 | 是否已更改 | JDBC 类型(V2) | Java 类(V2) | JDBC 类型(V1) | Java 类(V1) |
|---|---|---|---|---|---|
| Int8 | 否 | TINYINT | java.lang.Byte | TINYINT | java.lang.Byte |
| Int16 | 否 | SMALLINT | java.lang.Short | SMALLINT | java.lang.Short |
| Int32 | 否 | INTEGER | java.lang.Integer | INTEGER | java.lang.Integer |
| Int64 | 否 | BIGINT | java.lang.Long | BIGINT | java.lang.Long |
| UInt8 | 是 | OTHER | java.lang.Short | OTHER | com.clickhouse.data.value.UnsignedByte |
| UInt16 | 是 | OTHER | java.lang.Integer | OTHER | com.clickhouse.data.value.UnsignedShort |
| UInt32 | 是 | OTHER | java.lang.Long | OTHER | com.clickhouse.data.value.UnsignedInteger |
| UInt64 | 是 | OTHER | java.math.BigInteger | OTHER | com.clickhouse.data.value.UnsignedLong |
| Int128 | 否 | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| UInt128 | 否 | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| Int256 | 否 | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| UInt256 | 否 | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| Float32 | 否 | REAL | java.lang.Float | REAL | java.lang.Float |
| Float64 | 否 | DOUBLE | java.lang.Double | DOUBLE | java.lang.Double |
| Decimal32 | 否 | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal64 | 否 | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal128 | 否 | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal256 | 否 | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Bool | 否 | BOOLEAN | java.lang.Boolean | BOOLEAN | java.lang.Boolean |
| String | 否 | VARCHAR | java.lang.String | VARCHAR | java.lang.String |
| FixedString | 否 | CHAR | java.lang.String | CHAR | java.lang.String |
| Date | 是 | DATE | java.sql.Date | DATE | java.time.LocalDate |
| Date32 | 是 | DATE | java.sql.Date | DATE | java.time.LocalDate |
| DateTime | 是 | TIMESTAMP | java.sql.Timestamp | TIMESTAMP | java.time.OffsetDateTime |
| DateTime64 | 是 | TIMESTAMP | java.sql.Timestamp | TIMESTAMP | java.time.OffsetDateTime |
| UUID | 否 | OTHER | java.util.UUID | OTHER | java.util.UUID |
| IPv4 | 否 | OTHER | java.net.Inet4Address | OTHER | java.net.Inet4Address |
| IPv6 | 否 | OTHER | java.net.Inet6Address | OTHER | java.net.Inet6Address |
- 为了获得更好的可移植性,无符号类型会被映射为 Java 类型。
- 为了更好地兼容 JDBC,
Date和Date32会映射为java.sql.Date。不过,通过使用ResultSet.getObject(int, Class<T>)并将java.time.LocalDate.class作为第二个参数,也可以获取java.time.LocalDate。 Array映射到一个java.sql.Array对象。Tuple映射为一个java.sql.Struct对象,但也可以当作Array使用。