Skip to content

Commit b3e5d32

Browse files
authored
Merge pull request #656 from ClickHouse/compress_enhance
Clean up compression + add zstd
2 parents ba90cb7 + f9e7908 commit b3e5d32

14 files changed

+161
-352
lines changed

README.md

+13-11
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
# ClickHouse [![run-tests](https://github.com/ClickHouse/clickhouse-go/actions/workflows/run-tests.yml/badge.svg?branch=v2)](https://github.com/ClickHouse/clickhouse-go/actions/workflows/run-tests.yml) [![Go Reference](https://pkg.go.dev/badge/github.com/ClickHouse/clickhouse-go/v2.svg)](https://pkg.go.dev/github.com/ClickHouse/clickhouse-go/v2)
22

3-
Golang SQL database driver for [ClickHouse](https://clickhouse.com/).
3+
Golang SQL database client for [ClickHouse](https://clickhouse.com/).
44

55
## Versions
66

7-
There are two version of this driver, v1 and v2, available as separate branches.
7+
There are two version of this client, v1 and v2, available as separate branches.
88

99
**v1 is now in a state of a maintenance - we will only accept PRs for bug and security fixes.**
1010

1111
Users should use v2 which is production ready and [significantly faster than v1](#benchmark).
1212

1313
## Supported ClickHouse Versions
1414

15-
The driver is tested against the currently [supported versions](https://github.com/ClickHouse/ClickHouse/blob/master/SECURITY.md) of ClickHouse
15+
The client is tested against the currently [supported versions](https://github.com/ClickHouse/ClickHouse/blob/master/SECURITY.md) of ClickHouse
1616

1717
## Supported Golang Versions
1818

19-
| Driver Version | Golang Versions |
19+
| Client Version | Golang Versions |
2020
|----------------|-----------------|
2121
| => 2.0 <= 2.2 | 1.17, 1.18 |
2222
| >= 2.3 | 1.18 |
2323

2424
## Key features
2525

26-
* Uses ClickHouse native format for optimal performance. Utilises low level [ch-go](https://github.com/ClickHouse/ch-go) driver for encoding/decoding and compression (versions >= 2.3.0).
26+
* Uses ClickHouse native format for optimal performance. Utilises low level [ch-go](https://github.com/ClickHouse/ch-go) client for encoding/decoding and compression (versions >= 2.3.0).
2727
* Supports native ClickHouse TCP client-server protocol
2828
* Compatibility with [`database/sql`](#std-databasesql-interface) ([slower](#benchmark) than [native interface](#native-interface)!)
2929
* [`database/sql`](#std-databasesql-interface) supports http protocol for transport. (Experimental)
@@ -34,7 +34,7 @@ The driver is tested against the currently [supported versions](https://github.c
3434
* [Bulk write support](examples/native/batch/main.go) (for `database/sql` [use](examples/std/batch/main.go) `begin->prepare->(in loop exec)->commit`)
3535
* [AsyncInsert](benchmark/v2/write-async/main.go)
3636
* Named and numeric placeholders support
37-
* LZ4 compression support
37+
* LZ4/ZSTD compression support
3838
* External data
3939

4040
Support for the ClickHouse protocol advanced features using `Context`:
@@ -133,13 +133,15 @@ conn := clickhouse.OpenDB(&clickhouse.Options{
133133

134134
## Compression
135135

136-
Compression is supported over http and native. This is performed at a block level and is only used for inserts.
136+
ZSTD/LZ4 compression is supported over native and http. This is performed at a block level and is only used for inserts.
137+
138+
If using `Open` via the std interface and specifying a DSN, compression can be enabled via the `compress` flag. Currently, this is a boolean flag which enables `LZ4` compression.
137139

138140
Other compression methods will be added in future PRs.
139141

140142
## TLS/SSL
141143

142-
At a low level all driver connect methods (DSN/OpenDB/Open) will use the [Go tls package](https://pkg.go.dev/crypto/tls) to establish a secure connection. The driver knows to use TLS if the Options struct contains a non-nil tls.Config pointer.
144+
At a low level all client connect methods (DSN/OpenDB/Open) will use the [Go tls package](https://pkg.go.dev/crypto/tls) to establish a secure connection. The client knows to use TLS if the Options struct contains a non-nil tls.Config pointer.
143145

144146
Setting secure in the DSN creates a minimal tls.Config struct with only the InsecureSkipVerify field set (either true or false). It is equivalent to this code:
145147

@@ -220,13 +222,13 @@ go get -u github.com/ClickHouse/clickhouse-go/v2
220222

221223
## ClickHouse alternatives
222224

223-
Versions of this driver >=2.3.x utilise [ch-go](https://github.com/ClickHouse/ch-go) for their low level encoding/decoding. This low lever driver provides a high performance columnar interface and should be used in performance critical use cases. This driver provides more familar row orientated and `database/sql` semantics at the cost of some performance.
225+
Versions of this client >=2.3.x utilise [ch-go](https://github.com/ClickHouse/ch-go) for their low level encoding/decoding. This low lever client provides a high performance columnar interface and should be used in performance critical use cases. This client provides more familar row orientated and `database/sql` semantics at the cost of some performance.
224226

225-
Both drivers are supported by ClickHouse.
227+
Both clients are supported by ClickHouse.
226228

227229
## Third-party alternatives
228230

229-
* Database drivers:
231+
* Database client/clients:
230232
* [mailru/go-clickhouse](https://github.com/mailru/go-clickhouse) (uses the HTTP protocol)
231233
* [uptrace/go-clickhouse](https://github.com/uptrace/go-clickhouse) (uses the native TCP protocol with `database/sql`-like API)
232234
* Drivers with columnar interface:

clickhouse_options.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,21 @@ import (
2121
"context"
2222
"crypto/tls"
2323
"fmt"
24+
"github.com/ClickHouse/ch-go/compress"
2425
"net"
2526
"net/url"
2627
"strconv"
2728
"strings"
2829
"time"
29-
30-
"github.com/ClickHouse/clickhouse-go/v2/lib/compress"
3130
)
3231

33-
var CompressionLZ4 compress.Method = compress.LZ4
32+
type CompressionMethod compress.Method
33+
34+
const (
35+
CompressionNone = CompressionMethod(compress.None)
36+
CompressionLZ4 = CompressionMethod(compress.LZ4)
37+
CompressionZSTD = CompressionMethod(compress.ZSTD)
38+
)
3439

3540
type Auth struct { // has_control_character
3641
Database string
@@ -39,7 +44,7 @@ type Auth struct { // has_control_character
3944
}
4045

4146
type Compression struct {
42-
Method compress.Method
47+
Method CompressionMethod
4348
}
4449

4550
type ConnOpenStrategy uint8

conn.go

+7-9
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ func dial(ctx context.Context, addr string, num int, opt *Options) (*connect, er
5959
debugf = log.New(os.Stdout, fmt.Sprintf("[clickhouse][conn=%d][%s]", num, conn.RemoteAddr()), 0).Printf
6060
}
6161
}
62-
var compression bool
62+
compression := CompressionNone
6363
if opt.Compression != nil {
64-
compression = opt.Compression.Method == CompressionLZ4
64+
compression = opt.Compression.Method
6565
}
6666
var (
6767
connect = &connect{
@@ -95,7 +95,7 @@ type connect struct {
9595
released bool
9696
revision uint64
9797
structMap *structMap
98-
compression bool
98+
compression CompressionMethod
9999
// lastUsedIn time.Time
100100
connectedAt time.Time
101101
compressor *compress.Writer
@@ -169,12 +169,10 @@ func (c *connect) sendData(block *proto.Block, name string) error {
169169
if err := block.Encode(c.buffer, c.revision); err != nil {
170170
return err
171171
}
172-
if c.compression {
173-
// Performing compression.
174-
//
175-
// Note: only blocks are compressed.
172+
if c.compression != CompressionNone {
173+
// Performing compression. Note: only blocks are compressed.
176174
data := c.buffer.Buf[start:]
177-
if err := c.compressor.Compress(compress.LZ4, data); err != nil {
175+
if err := c.compressor.Compress(compress.Method(c.compression), data); err != nil {
178176
return errors.Wrap(err, "compress")
179177
}
180178
c.buffer.Buf = append(c.buffer.Buf[:start], c.compressor.Data...)
@@ -193,7 +191,7 @@ func (c *connect) readData(packet byte, compressible bool) (*proto.Block, error)
193191
if _, err := c.reader.Str(); err != nil {
194192
return nil, err
195193
}
196-
if compressible && c.compression {
194+
if compressible && c.compression != CompressionNone {
197195
c.reader.EnableCompression()
198196
defer c.reader.DisableCompression()
199197
}

conn_http.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ func dialHttp(ctx context.Context, addr string, num int, opt *Options) (*httpCon
7070
query.Set(k, fmt.Sprint(v))
7171
}
7272
query.Set("default_format", "Native")
73-
var compression bool
73+
compression := CompressionNone
7474
if opt.Compression != nil {
75-
compression = opt.Compression.Method == CompressionLZ4
75+
compression = opt.Compression.Method
7676
}
7777
u.RawQuery = query.Encode()
7878

@@ -120,7 +120,7 @@ type httpConnect struct {
120120
client *http.Client
121121
location *time.Location
122122
buffer *chproto.Buffer
123-
compression bool
123+
compression CompressionMethod
124124
compressor *compress.Writer
125125
}
126126

@@ -137,10 +137,10 @@ func (h *httpConnect) writeData(block *proto.Block) error {
137137
if err := block.Encode(h.buffer, 0); err != nil {
138138
return err
139139
}
140-
if h.compression {
140+
if h.compression != CompressionNone {
141141
// Performing compression. Supported and requires
142142
data := h.buffer.Buf[start:]
143-
if err := h.compressor.Compress(compress.LZ4, data); err != nil {
143+
if err := h.compressor.Compress(compress.Method(h.compression), data); err != nil {
144144
return errors.Wrap(err, "compress")
145145
}
146146
h.buffer.Buf = append(h.buffer.Buf[:start], h.compressor.Data...)
@@ -150,6 +150,10 @@ func (h *httpConnect) writeData(block *proto.Block) error {
150150

151151
func (h *httpConnect) readData(reader *chproto.Reader) (*proto.Block, error) {
152152
var block proto.Block
153+
if h.compression != CompressionNone {
154+
reader.EnableCompression()
155+
defer reader.DisableCompression()
156+
}
153157
if err := block.Decode(reader, 0); err != nil {
154158
return nil, err
155159
}

conn_http_batch.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ func (b *httpBatch) Send() (err error) {
170170

171171
options := queryOptions(b.ctx)
172172
// only compress blocks
173-
if b.conn.compression {
173+
if b.conn.compression != CompressionNone {
174174
options.settings["decompress"] = "1"
175175
}
176176
options.settings["query"] = b.query

conn_http_query.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ func (h *httpConnect) query(ctx context.Context, release func(*connect, error),
3434
if err != nil {
3535
return nil, err
3636
}
37-
3837
options := queryOptions(ctx)
38+
if h.compression != CompressionNone {
39+
options.settings["compress"] = "1"
40+
}
3941
res, err := h.sendQuery(ctx, strings.NewReader(query), &options, nil)
4042
if err != nil {
4143
return nil, err

conn_send_query.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func (c *connect) sendQuery(body string, o *QueryOptions) error {
3131
Body: body,
3232
Span: o.span,
3333
QuotaKey: o.quotaKey,
34-
Compression: c.compression,
34+
Compression: c.compression != CompressionNone,
3535
InitialAddress: c.conn.LocalAddr().String(),
3636
Settings: c.settings(o.settings),
3737
}

lib/compress/compress.go

-41
This file was deleted.

lib/compress/compress_reader.go

-111
This file was deleted.

0 commit comments

Comments
 (0)