Skip to content

[v0.10.0-rc1] Binary String Support #2911

Merged
chernser merged 17 commits into
v0.10.0from
07/06/26/binary_string_support
Jul 22, 2026
Merged

[v0.10.0-rc1] Binary String Support #2911
chernser merged 17 commits into
v0.10.0from
07/06/26/binary_string_support

Conversation

@chernser

@chernser chernser commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

There are a few problems with reading binary strings:

  • they are not utf-8 strings and should not be decoded like that
  • reading big binary blobs may cause OOM because currently strings are created on read.

This PR introduces StringValue that acts as byte[] holder to create String ad-hoc instead of when read. So strings that suppose to be read via byte[] will stay as byte[].

This affects also JDBC where ResultSet has getBinaryStream for such cases. Now it is supported operation.

Part of #2263

Checklist

Delete items not relevant to your PR:

  • Closes #
  • Unit and integration tests covering the common scenarios were added
  • A human-readable description of the changes was provided to include in CHANGELOG
  • For significant changes, documentation in https://github.com/ClickHouse/clickhouse-docs was updated with further explanations or tutorials

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Repository collaborators can run the JMH benchmark suite against this PR by commenting:

/benchmark

Optional regression threshold override (Δ% on Time or Alloc/op; defaults to 10%):

/benchmark threshold=15

Only one benchmark run per PR is active at a time — issuing a new /benchmark comment cancels the previous run. After the run finishes a separate comment will be posted comparing it against the latest scheduled run on main; the PR check fails if any benchmark regresses by more than the threshold.

@chernser chernser changed the title 07/06/26/binary string support [v0.10.0-rc1] Binary String Support Jul 6, 2026
@chernser
chernser marked this pull request as ready for review July 6, 2026 23:22
@chernser
chernser requested a review from mzitnik as a code owner July 6, 2026 23:22
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Triage

Category: featureRisk: high

Summary
This PR adds binary string support to client-v2 and jdbc-v2, addressing issue #2263 (large string / binary blob handling). The core change introduces a new internal StringValue class that defers UTF-8 decoding — raw bytes are held and a String is only materialised on demand — preventing OOM for large binary blobs and preserving non-UTF-8 byte sequences. The feature is gated behind a new BINARY_STRING_SUPPORT config property (default false). Hot-path reads in BinaryStreamReader and AbstractBinaryFormatReader are modified to route through the flag, the public ClickHouseBinaryFormatWriter interface gains two new setString(…, byte[]) overloads, RowBinaryFormatSerializer gains a writeString(byte[]) method, and jdbc-v2's ResultSetImpl adds getBinaryStream support.

What this impacts

  • client-v2 read path: BinaryStreamReader, AbstractBinaryFormatReader, MapBackedRecord, DataTypeConverter — all modified
  • client-v2 write path: ClickHouseBinaryFormatWriter (public interface), RowBinaryFormatWriter, RowBinaryFormatSerializer
  • jdbc-v2 result reading: ResultSetImpl, JdbcUtils
  • New internal type StringValue introduced in com.clickhouse.client.api.data_formats.internal
  • New client-level and per-operation config property BINARY_STRING_SUPPORT

Concerns

  • Readers & Writers rule (HIGH): BinaryStreamReader and AbstractBinaryFormatReader (the core read hot-path in client-v2) are both modified; RowBinaryFormatWriter/RowBinaryFormatSerializer on the write path are also changed.
  • Public API shape changed (HIGH): ClickHouseBinaryFormatWriter is a public interface and gains two new abstract methods (setString(String, byte[]), setString(int, byte[])). Any third-party implementor of this interface will get an AbstractMethodError at runtime unless recompiled — a binary-breaking change. The CHANGELOG acknowledges this.
  • Large diff (HIGH): 2 072 additions + 43 deletions across 27 files.
  • The feature is properly gated behind BINARY_STRING_SUPPORT=false by default, so the existing code path is not affected when the flag is off.

Required reviewer action

  • At least one human reviewer required.

Comment thread jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

📊 ClickHouse client benchmark results

commit cbd500f · mode pr-vs-main · run 29268438340

📊 Benchmark tables · ⚠️ regressions — click to expand

Timings (lower = better) — Δ vs baseline, + = slower on the PR build. cold = first iteration; warm = mean of the rest; σ = stddev of the warm iterations.

query_label base cold PR cold base warm PR warm Δ warm base σ PR σ
SelectHitsCount (compression=on) 383 387 9.2 6.2 -32.4% 2.1 0.5
SelectHits (compression=on) 4536 4577 3460 3350 -3.2% 40.1 48.1
InsertHits (compression=on) 1040 1080 890 898 +0.8% 11.4 37.2
SelectHitsCount (compression=on) 201 193 5.5 4.8 -13.6% 0.6 1.0
SelectHits (compression=on) 4867 4883 3900 3869 -0.8% 28.9 29.2
InsertHits (compression=on) 1072 1089 887 878 -1.0% 44.8 34.0
SelectHitsCount (compression=on) 454 438 41.2 42.2 +2.4% 2.6 2.5
SelectHits (compression=on) 3234 3362 2102 2282 +8.6% 61.9 36.9
InsertHits (compression=on) 1926 1959 1671 1824 +9.2% 153 149
SelectHitsCount (compression=on) 419 422 18.0 18.8 +4.2% 2.7 1.7
SelectHits (compression=on) 5398 4646 3521 3466 -1.6% 105 91.2
InsertHits (compression=on) 3310 3327 2864 2722 -5.0% 219 256

Resource usage (lower = better) (per-iteration averages)

peak_memory_mb

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 116 116 +0.3%
clickhouse-java-v1 SelectHits (compression=on) 1245 1238 -0.5%
clickhouse-java-v1 InsertHits (compression=on) 1852 1857 +0.3%
clickhouse-java-v2 SelectHitsCount (compression=on) 118 117 -0.7%
clickhouse-java-v2 SelectHits (compression=on) 1234 1236 +0.2%
clickhouse-java-v2 InsertHits (compression=on) 1851 1859 +0.4%
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 124 127 +1.9%
clickhouse-jdbc-v1 SelectHits (compression=on) 1243 1248 +0.4%
clickhouse-jdbc-v1 InsertHits (compression=on) 5061 6273 +23.9%
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 131 131 +0.1%
clickhouse-jdbc-v2 SelectHits (compression=on) 1253 1243 -0.9%
clickhouse-jdbc-v2 InsertHits (compression=on) 9349 6939 -25.8%

user_cpu_ms

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 1211 1198 -1.1%
clickhouse-java-v1 SelectHits (compression=on) 19148 18722 -2.2%
clickhouse-java-v1 InsertHits (compression=on) 13292 13317 +0.2%
clickhouse-java-v2 SelectHitsCount (compression=on) 1389 1218 -12.3%
clickhouse-java-v2 SelectHits (compression=on) 22082 21726 -1.6%
clickhouse-java-v2 InsertHits (compression=on) 13281 13435 +1.2%
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 1562 1616 +3.5%
clickhouse-jdbc-v1 SelectHits (compression=on) 12993 13005 +0.1%
clickhouse-jdbc-v1 InsertHits (compression=on) 18847 19671 +4.4%
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 1489 1393 -6.4%
clickhouse-jdbc-v2 SelectHits (compression=on) 20105 20360 +1.3%
clickhouse-jdbc-v2 InsertHits (compression=on) 22200 21956 -1.1%

system_cpu_ms

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 277 353 +27.4%
clickhouse-java-v1 SelectHits (compression=on) 1792 1844 +2.9%
clickhouse-java-v1 InsertHits (compression=on) 1035 1154 +11.5%
clickhouse-java-v2 SelectHitsCount (compression=on) 257 323 +25.7%
clickhouse-java-v2 SelectHits (compression=on) 1041 1393 +33.8% ⚠️
clickhouse-java-v2 InsertHits (compression=on) 1164 1113 -4.4%
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 354 238 -32.8%
clickhouse-jdbc-v1 SelectHits (compression=on) 1244 1633 +31.3% ⚠️
clickhouse-jdbc-v1 InsertHits (compression=on) 2591 3749 +44.7% ⚠️
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 369 519 +40.7% ⚠️
clickhouse-jdbc-v2 SelectHits (compression=on) 1382 1087 -21.3%
clickhouse-jdbc-v2 InsertHits (compression=on) 4134 3545 -14.2%

voluntary_context_switches

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 6500 8173 +25.7%
clickhouse-java-v1 SelectHits (compression=on) 30359 25492 -16.0%
clickhouse-java-v1 InsertHits (compression=on) 13647 14669 +7.5%
clickhouse-java-v2 SelectHitsCount (compression=on) 8937 8893 -0.5%
clickhouse-java-v2 SelectHits (compression=on) 19800 21304 +7.6%
clickhouse-java-v2 InsertHits (compression=on) 14776 15919 +7.7%
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 9173 8584 -6.4%
clickhouse-jdbc-v1 SelectHits (compression=on) 23357 25982 +11.2%
clickhouse-jdbc-v1 InsertHits (compression=on) 20196 20023 -0.9%
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 9826 10231 +4.1%
clickhouse-jdbc-v2 SelectHits (compression=on) 21863 21554 -1.4%
clickhouse-jdbc-v2 InsertHits (compression=on) 18178 17493 -3.8%

involuntary_context_switches

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 4 20 +400.0% ⚠️
clickhouse-java-v1 SelectHits (compression=on) 82 54 -34.1%
clickhouse-java-v1 InsertHits (compression=on) 27 41 +51.9% ⚠️
clickhouse-java-v2 SelectHitsCount (compression=on) 3 4 +33.3% ⚠️
clickhouse-java-v2 SelectHits (compression=on) 38 43 +13.2%
clickhouse-java-v2 InsertHits (compression=on) 39 42 +7.7%
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 4 3 -25.0%
clickhouse-jdbc-v1 SelectHits (compression=on) 28 52 +85.7% ⚠️
clickhouse-jdbc-v1 InsertHits (compression=on) 42 64 +52.4% ⚠️
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 1 3 +200.0% ⚠️
clickhouse-jdbc-v2 SelectHits (compression=on) 87 67 -23.0%
clickhouse-jdbc-v2 InsertHits (compression=on) 60 52 -13.3%

major_page_faults

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 0 0
clickhouse-java-v1 SelectHits (compression=on) 0 0
clickhouse-java-v1 InsertHits (compression=on) 0 0
clickhouse-java-v2 SelectHitsCount (compression=on) 0 2 +∞% ⚠️
clickhouse-java-v2 SelectHits (compression=on) 0 0
clickhouse-java-v2 InsertHits (compression=on) 0 0
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 0 0
clickhouse-jdbc-v1 SelectHits (compression=on) 0 0
clickhouse-jdbc-v1 InsertHits (compression=on) 0 0
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 0 0
clickhouse-jdbc-v2 SelectHits (compression=on) 0 0
clickhouse-jdbc-v2 InsertHits (compression=on) 0 0

minor_page_faults

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 31201 31032 -0.5%
clickhouse-java-v1 SelectHits (compression=on) 332312 319479 -3.9%
clickhouse-java-v1 InsertHits (compression=on) 485290 483604 -0.3%
clickhouse-java-v2 SelectHitsCount (compression=on) 31748 31056 -2.2%
clickhouse-java-v2 SelectHits (compression=on) 320818 324021 +1.0%
clickhouse-java-v2 InsertHits (compression=on) 487384 490027 +0.5%
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 33320 33859 +1.6%
clickhouse-jdbc-v1 SelectHits (compression=on) 328260 330354 +0.6%
clickhouse-jdbc-v1 InsertHits (compression=on) 1.3M 1.6M +23.3%
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 34896 35833 +2.7%
clickhouse-jdbc-v2 SelectHits (compression=on) 330829 327068 -1.1%
clickhouse-jdbc-v2 InsertHits (compression=on) 2.4M 1.8M -24.5%

instructions

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 6.3G 6.3G +1.1%
clickhouse-java-v1 SelectHits (compression=on) 215.5G 227.9G +5.7%
clickhouse-java-v1 InsertHits (compression=on) 98.6G 99.1G +0.5%
clickhouse-java-v2 SelectHitsCount (compression=on) 6.6G 6.3G -3.4%
clickhouse-java-v2 SelectHits (compression=on) 271.6G 273.2G +0.6%
clickhouse-java-v2 InsertHits (compression=on) 100.5G 99.8G -0.7%
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 7.8G 7.7G -0.6%
clickhouse-jdbc-v1 SelectHits (compression=on) 151.1G 152.8G +1.1%
clickhouse-jdbc-v1 InsertHits (compression=on) 166.3G 175.7G +5.6%
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 7.8G 8.0G +2.6%
clickhouse-jdbc-v2 SelectHits (compression=on) 237.5G 239.9G +1.0%
clickhouse-jdbc-v2 InsertHits (compression=on) 195.8G 196.3G +0.3%

cpu_cycles

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 3.9G 4.0G +2.0%
clickhouse-java-v1 SelectHits (compression=on) 60.8G 60.3G -0.9%
clickhouse-java-v1 InsertHits (compression=on) 41.7G 42.0G +0.8%
clickhouse-java-v2 SelectHitsCount (compression=on) 4.2G 3.9G -5.7%
clickhouse-java-v2 SelectHits (compression=on) 69.3G 69.1G -0.3%
clickhouse-java-v2 InsertHits (compression=on) 42.3G 42.4G +0.3%
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 5.0G 4.9G -1.9%
clickhouse-jdbc-v1 SelectHits (compression=on) 40.7G 41.7G +2.5%
clickhouse-jdbc-v1 InsertHits (compression=on) 59.5G 64.4G +8.1%
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 4.8G 5.0G +4.3%
clickhouse-jdbc-v2 SelectHits (compression=on) 63.9G 63.8G -0.3%
clickhouse-jdbc-v2 InsertHits (compression=on) 71.4G 70.7G -1.1%

cache_misses

client query_label base PR Δ
clickhouse-java-v1 SelectHitsCount (compression=on) 0 0
clickhouse-java-v1 SelectHits (compression=on) 0 0
clickhouse-java-v1 InsertHits (compression=on) 0 0
clickhouse-java-v2 SelectHitsCount (compression=on) 0 0
clickhouse-java-v2 SelectHits (compression=on) 0 0
clickhouse-java-v2 InsertHits (compression=on) 0 0
clickhouse-jdbc-v1 SelectHitsCount (compression=on) 0 0
clickhouse-jdbc-v1 SelectHits (compression=on) 0 0
clickhouse-jdbc-v1 InsertHits (compression=on) 0 0
clickhouse-jdbc-v2 SelectHitsCount (compression=on) 0 0
clickhouse-jdbc-v2 SelectHits (compression=on) 0 0
clickhouse-jdbc-v2 InsertHits (compression=on) 0 0

@mzitnik

mzitnik commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@chernser, ClickHouse client benchmark results from a few days ago indicate some ⚠️ regressions. Can you take a look
We also have failing cloud tests.

@chernser

chernser commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

@mzitnik client benchmark is not reliable in CI. I will run them locally and post results. By default we are not using BinaryStrings so it should show no regression.

Updated:
This is a new one. Will investigate.

@chernser
chernser requested a review from mzitnik July 15, 2026 22:35

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit db53728. Configure here.

@chernser

chernser commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

@mzitnik
regarding the benchmark tests:

  • tests were run in github runner and have very unstable results. I've tested on main and they give different numbers
  • I've run locally 5 iterations with 15 time window. Machine was doing only benchmark
  • local tests shown only slight diff withing 8% range (in V1 code too)
  • local tests were done with no fix and with fix but binary string turned off.

01-baseline.json
02-after_fix.json

image

@chernser

Copy link
Copy Markdown
Contributor Author

@mzitnik
when binary enabled no issue found, too
image
03-after_fix_enabled.json

@chernser
chernser merged commit 9dd3229 into v0.10.0 Jul 22, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants