Skip to content

iliaal/php_clickhouse

 
 

Repository files navigation

php_clickhouse

Tests Version License: PHP-3.01 Follow @iliaa

Native PHP extension for ClickHouse, built on the official ClickHouse/clickhouse-cpp client. Connects over the binary TCP protocol with LZ4 / ZSTD compression and optional TLS.

Status

Soft fork of SeasX/SeasClick, which appears unmaintained. The last accepted external PR there is from 2020, and several follow-up PRs have been pending for years. This fork:

  • Renames the extension to php_clickhouse (module clickhouse, classes ClickHouse / ClickHouseException)
  • Upgrades the vendored client from artpaul-fork v1.x to the official ClickHouse/clickhouse-cpp v2.6.1
  • Adds Date32 / Time / Time64 / DateTime64 / Int128 / UInt128 / Decimal128 / LowCardinality / Map column types, multi-endpoint failover, ZSTD compression, query_id propagation, and TLS
  • Ships an updated test suite, CI, PIE-based packaging, and benchmarks

The original SeasClick and SeasClickException class names continue to work as deprecated aliases for the 0.5.x cycle.

Install

via PIE (the PHP Foundation's PECL successor):

pie install iliaal/php_clickhouse

with TLS support:

pie install iliaal/php_clickhouse --enable-clickhouse-openssl

Building from source:

git clone https://github.com/iliaal/php_clickhouse.git
cd php_clickhouse
phpize
./configure                              # default build
./configure --enable-clickhouse-openssl  # with TLS, requires OpenSSL development headers
                                         #   (libssl-dev on Debian/Ubuntu, openssl-devel
                                         #    on RHEL/Fedora, openssl-dev on Alpine)
make && sudo make install

Add extension=clickhouse.so to your php.ini. The build needs a C++17-capable compiler (GCC 8+, Clang 7+); LZ4, ZSTD, abseil-int128, and CityHash are vendored under lib/clickhouse-cpp/contrib/.

Only NTS PHP builds are supported. The extension stores Client state in process-global maps; under ZTS the same handle space is shared across worker threads, so the wrapper refuses to load.

Test server

For development and integration tests, the simplest path is the official ClickHouse server image:

docker run -d --name clickhouse-test \
    --ulimit nofile=262144:262144 \
    -p 9000:9000 -p 8123:8123 -p 9440:9440 \
    -e CLICKHOUSE_USER=test \
    -e CLICKHOUSE_PASSWORD=test \
    clickhouse/clickhouse-server:latest

Stop and clean up: docker rm -f clickhouse-test.

Quick example

<?php
$ch = new ClickHouse([
    "host"        => "127.0.0.1",
    "port"        => 9000,
    "database"    => "test",
    "user"        => "default",
    "passwd"      => "",
    "compression" => "lz4",   // or "zstd" / true / false
]);

$ch->execute("CREATE TABLE IF NOT EXISTS events (
    id UInt32, ts DateTime64(3), tag LowCardinality(String)
) ENGINE = Memory");

$ch->insert("events", ["id", "ts", "tag"], [
    [1, time(), "alpha"],
    [2, time(), "beta"],
]);

foreach ($ch->select("SELECT id, ts, tag FROM events ORDER BY id",
                     [], ClickHouse::DATE_AS_STRINGS) as $row) {
    print_r($row);
}

Supported data types

  • Array(T) (single-level)
  • Date, Date32, DateTime, DateTime64(N[, timezone])
  • Time, Time64(N) (server side requires ClickHouse 25.x or later)
  • Decimal, Decimal32, Decimal64, Decimal128(P, S) (read/write as scaled-integer strings)
  • Enum8, Enum16
  • FixedString(N)
  • Float32, Float64
  • Int8Int64, UInt8UInt64
  • Int128, UInt128 (round-trip as decimal strings; PHP integers are 64-bit)
  • IPv4, IPv6
  • LowCardinality(String), LowCardinality(FixedString(N))
  • Map(K, V) for (String, String), (String, Int64), (String, UInt64), (String, Float64), (Int64, String). Other K/V pairs are read-only via the lib's generic factory.
  • Nullable(T)
  • String
  • Tuple (read-only)
  • UUID

Configuration reference

All keys go in the array passed to new ClickHouse([...]).

Connection

Key Type Default Description
host string 127.0.0.1 Server host
port int 9000 Native TCP port (or 9440 for TLS)
database string default Default database
user string default Username
passwd string (empty) Password
endpoints array (none) List of [{host, port}, ...] for round-robin failover. Tried in order on connect failure.

Compression

Key Type Default Description
compression bool / string false false/"none" = uncompressed; true/"lz4" = LZ4 (fast); "zstd" = ZSTD (denser)
max_compression_chunk_size int 65535 Block size used by the compressor

Timeouts and retry

Key Type Default Description
connect_timeout int (sec) 5 TCP connect deadline
receive_timeout int (sec) 0 Read deadline (0 = no timeout)
send_timeout int (sec) 0 Write deadline
retry_count int 1 Send retries on transient failure
retry_timeout int (sec) 5 Sleep between retries
tcp_nodelay bool true TCP_NODELAY
tcp_keepalive bool false TCP keepalive
tcp_keepalive_idle int (sec) 60 Idle time before first keepalive probe
tcp_keepalive_intvl int (sec) 5 Interval between probes
tcp_keepalive_cnt int 3 Failed probes before declaring dead

TLS (build with --enable-clickhouse-openssl)

Key Type Default Description
ssl bool false Enable TLS
ssl_min_protocol_version string tls1.2 Minimum protocol; one of tls1.0, tls1.1, tls1.2, tls1.3
ssl_skip_verify bool false Skip cert validation; dev only
ssl_use_default_ca bool true Trust the system CA bundle
ssl_ca_files string | array (none) PEM CA file path(s)
ssl_ca_directory string (none) OpenSSL hashed-cert directory

Building without --enable-clickhouse-openssl and passing ssl => true raises ClickHouseException at construct time.

Methods

$ch = new ClickHouse(array $config);

// Schema / DDL
$ch->execute(string $sql, array $params = [], string $query_id = "");

// Read
$rows = $ch->select(string $sql,
                    array $params = [],
                    int $fetch_mode = 0,
                    string $query_id = "");

// Bulk insert (entire dataset in one call)
$ch->insert(string $table, array $columns, array $values,
            string $query_id = "");

// Streaming insert (open block, append, close)
$ch->writeStart(string $table, array $columns, string $query_id = "");
$ch->write(array $values);
$ch->write(array $more_values);
$ch->writeEnd();

$ch->ping();          // returns true on success, throws on failure

fetch_mode is a bitmask of ClickHouse::FETCH_ONE, ClickHouse::FETCH_KEY_PAIR, ClickHouse::FETCH_COLUMN, and ClickHouse::DATE_AS_STRINGS.

Benchmarks

PHP 8.4.22 / ClickHouse 26.3.9.8 / localhost loopback / Memory table (no disk).

Compared against smi2/phpClickHouse, the most popular pure-PHP HTTP client.

Each cell is total wall-clock seconds for selectCount queries plus a single bulk insert of dataCount rows.

dataCount × selectCount × limit phpClickHouse (HTTP) php_clickhouse (uncompressed) php_clickhouse (LZ4) php_clickhouse (ZSTD)
10000 × 1 × 5000 0.112 0.085 0.074 0.023
10000 × 1 × 5000 0.104 0.030 0.024 0.081
10000 × 100 × 5000 0.298 0.263 0.209 0.218
10000 × 100 × 10000 0.303 0.210 0.265 0.215
1000 × 200 × 500 0.558 0.416 0.415 0.413
1000 × 200 × 1000 0.611 0.408 0.410 0.395
1000 × 500 × 500 1.428 1.063 0.976 0.982
1000 × 500 × 1000 1.383 0.959 1.025 1.030
1000 × 800 × 500 2.477 1.533 1.569 1.543
1000 × 800 × 1000 2.498 1.588 1.563 1.519

At high select counts the native binary protocol runs 30-40% faster than the HTTP client. On small bursts (dataCount=10000, selectCount=1), php_clickhouse with ZSTD or LZ4 is fastest. To reproduce, see bench/.

License

The PHP-side wrapper is licensed under PHP-3.01.

The vendored client library at lib/clickhouse-cpp/ is ClickHouse/clickhouse-cpp, licensed under the Apache License 2.0.

The vendored compression libraries (lib/clickhouse-cpp/contrib/lz4/, contrib/zstd/, contrib/cityhash/) carry BSD-style licenses; abseil int128 (contrib/absl/) is Apache 2.0. See each subdirectory for the exact text.

Credits

php_clickhouse started as a fork of SeasX/SeasClick by SeasX Group (ahhhh.wang@gmail.com). The original PR-4 work to add fetch modes landed in 2019 and the upstream maintainer hasn't accepted external PRs since. Independent re-vendoring, port to clickhouse-cpp v2.6.1, new types, TLS, and packaging are by Ilia Alshanetsky ilia@ilia.ws.

Contributing

See CONTRIBUTING.md. Security issues: SECURITY.md.

About

Native PHP extension for ClickHouse using the official ClickHouse/clickhouse-cpp client. Soft fork of SeasX/SeasClick.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • C 69.9%
  • C++ 27.1%
  • PHP 1.7%
  • Assembly 0.4%
  • CMake 0.3%
  • NASL 0.2%
  • Other 0.4%