diff --git a/CHANGELOG.md b/CHANGELOG.md index ecea0c4f7..ed50c9257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -180,6 +180,10 @@ now required to work with server. (https://github.com/ClickHouse/clickhouse-java ### Bug Fixes +- **[client-v2,jdbc-v2]** - Replaced slow HTTP LZ4 compression with compressing stream from +`lz4-java` library. Client uses Apache Compress to handle HTTP compression (because it has +convenient factory for many compressions methods. However, Apache Compress uses slow LZ4 implementation what causes very slow inserts. Now `lz4-java` used for insert. Query still slow but will be fix in future releases (need refactoring and custom implementation to solve it). Using `ZSTD` for queries should solve the issue.(https://github.com/ClickHouse/clickhouse-java/issues/2273). + - **[client-v2]** Fixed writing a `String` value into a `UUID` column (also as an `Array`/`Tuple` element or a `Map` key) failing with `ClassCastException`. The string is now parsed with `UUID.fromString`; a string it cannot parse is rejected on the client with an `IllegalArgumentException`. (https://github.com/ClickHouse/clickhouse-java/issues/3132) diff --git a/client-v2/src/main/java/com/clickhouse/client/api/internal/CompressedEntity.java b/client-v2/src/main/java/com/clickhouse/client/api/internal/CompressedEntity.java index 2e61c7d65..40f370843 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/internal/CompressedEntity.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/internal/CompressedEntity.java @@ -1,5 +1,6 @@ package com.clickhouse.client.api.internal; +import net.jpountz.lz4.LZ4FrameOutputStream; import org.apache.commons.compress.compressors.CompressorException; import org.apache.commons.compress.compressors.CompressorStreamFactory; import org.apache.hc.core5.function.Supplier; @@ -51,13 +52,21 @@ public void writeTo(OutputStream outStream) throws IOException { throw new UnsupportedOperationException("Unsupported: writing compressed response to elsewhere"); } - try (OutputStream compressingStream = compressorStreamFactory.createCompressorOutputStream(compressionAlgo, outStream)){ + try (OutputStream compressingStream = createCompressingStream(outStream)){ httpEntity.writeTo(compressingStream); } catch (CompressorException e) { throw new IOException("Failed to create compressing output stream", e); } } + private OutputStream createCompressingStream(OutputStream out) throws IOException { + if (CompressorStreamFactory.LZ4_FRAMED.equalsIgnoreCase(compressionAlgo)) { + return new LZ4FrameOutputStream(out, LZ4FrameOutputStream.BLOCKSIZE.SIZE_256KB); + } else { + return compressorStreamFactory.createCompressorOutputStream(compressionAlgo, out); + } + } + @Override public boolean isStreaming() { return httpEntity.isStreaming(); diff --git a/performance/src/main/java/com/clickhouse/benchmark/clients/Compression.java b/performance/src/main/java/com/clickhouse/benchmark/clients/Compression.java index 657dde518..9418dbdfb 100644 --- a/performance/src/main/java/com/clickhouse/benchmark/clients/Compression.java +++ b/performance/src/main/java/com/clickhouse/benchmark/clients/Compression.java @@ -6,7 +6,7 @@ import com.clickhouse.client.api.Client; import com.clickhouse.client.api.insert.InsertResponse; import com.clickhouse.client.api.insert.InsertSettings; -import com.clickhouse.client.api.internal.ClickHouseLZ4OutputStream; +import com.clickhouse.client.api.internal.CompressedBlockOutputStream; import com.clickhouse.client.api.query.QueryResponse; import com.clickhouse.client.api.query.QuerySettings; import com.clickhouse.client.config.ClickHouseClientOption; @@ -78,7 +78,7 @@ public void CompressingOutputStreamV1(DataState dataState) { public void CompressingOutputStreamV2(DataState dataState) { DataSet dataSet = dataState.dataSet; try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ClickHouseLZ4OutputStream out = new ClickHouseLZ4OutputStream(baos, + CompressedBlockOutputStream out = new CompressedBlockOutputStream.LZ4OutputStream(baos, factory.fastCompressor(), COMPRESS_BUFFER_SIZE)) { for (byte[] bytes : dataSet.getBytesList(dataSet.getFormat())) { out.write(bytes);