slkxmail/clickhouse-client

简单的 PHP Clickhouse 客户端

v1.0.0 2018-09-03 20:01 UTC

This package is not auto-updated.

Last update: 2024-09-26 21:21:47 UTC


README

这是一个 Clickhouse 客户端的简单版本(使用 HTTP 接口)。这个版本提供了最接近 HTTP 接口的访问方式,允许你在 PHP 应用程序中使用 Clickhouse 数据库的最大功能。

CircleCI MIT Licence

安装

使用 composer 的基本安装

composer require bozerkins/clickhouse-client

配置

use ClickhouseClient\Client\Config;

$config = new Config(
    // basic connection information
    ['host' => '127.0.0.1', 'port' => '8123', 'protocol' => 'http'],
    // settings
    ['database' => 'default'],
    // credentials
    ['user' => 'default', 'password' => '']
);

你可以在第二个参数中传递额外的设置,包括数据库名称。

完整的设置列表可以在 Clickhouse 文档的 设置部分 中找到。

如果你使用的是默认配置,你不需要定义所有这些。

例如,如果你想创建一个只读访问的客户端对象,请传递 "readonly" 参数。

$config = new Config(
    // basic connection information - set to default
    [],
    // settings
    [ 'database' => 'my_shiny_database', 'readonly' => 1 ]
    // credentials - set to defauult
    []
);

与 Clickhouse 数据库的通信使用 php-curl 库。如果你想更紧密地控制查询执行,你可以在 Config 构造函数中传递第四个参数,包含 php-curl 库参数。

例如,如果我们想设置 5 秒的连接超时,我们会创建以下配置

use ClickhouseClient\Client\Config;

$config = new Config(
    // basic connection information - set to default
    [],
    // settings
    [ 'database' => 'my_shiny_database', 'readonly' => 1 ]
    // credentials - set to defauult
    [],
    // additional CURL options
    [ CURLOPT_TIMEOUT => 5 ]
);

支持的常量完整列表可以在 curl_setopt 函数文档 中找到。

你可以在创建配置对象后定义凭据或设置

use ClickhouseClient\Client\Config;

$config = new Config(
    // basic connection information
    ['host' => '127.0.0.1', 'port' => '8123', 'protocol' => 'http']
);
$config->setUser('user');
$config->setPassword('password');
$config->change('database', 'new-db');

更改基本连接信息和 curl 设置的功能尚未实现,因为这从概念上和技术上都应该被视为一个新的客户端。

客户端

创建客户端相对简单。

use ClickhouseClient\Client\Client;

$client= new Client($config);

从 Clickhouse 读取

从 Clickhouse 读取数据有几种方法。

简单查询

此方法主要用于从 Clickhouse 获取统计信息、聚合数据。

# perform select
$response = $client->query(
    'SELECT * FROM system.numbers LIMIT 10'
);
# get decoded output - database response
$response->getContent();
# get raw output string - raw string received from clickhouse
$response->getOutput();
# get communication details - curl defails for the request
$response->getDetails();
# and a neat shortcut for getting http response code
$response->getHttpCode();

每个客户端查询都会返回一个响应,其中包含执行连接和响应的所有信息。

将查询数据输入到流中

可以直接将数据从 Clickhouse 读取到流中,例如文件。

# create a stream - open a file
$stream = fopen('/tmp/file-to-read-data-into', 'r+');
# query data into the file
$client->queryStream(
    "SELECT * FROM system.numbers LIMIT 5", 
    $stream
);

将查询数据输入到闭包(函数可调用)

此方法在你想将一个 Clickhouse 响应分成几个目的地时很有用。

# open file 1
$file1 = fopen('/tmp/file-to-read-data-into-1', 'r+');
# open file 2
$file2 = fopen('/tmp/file-to-read-data-into-2', 'r+');

# query data, process response with anonymous function
$client->queryClosure(
   "SELECT * FROM system.numbers LIMIT 100", 
   function($line) use ($file1, $file2) {
       $row = json_decode($line);
       if ($row['number'] % 2 === 0) {
           fwrite($file1, $line . PHP_EOL);
       } else {
           fwrite($file2, $line . PHP_EOL);
       }
    }
);

写入 Clickhouse

写入数据库也有几种方式。

简单插入

写入数据库最常见的方式。

# write data to a table
$client->write('INSERT INTO myTable VALUES (1), (2), (3)');

注意:clickhouse 没有像 MySQL / Oracle 等数据库的转义机制。请参阅其他插入方法以安全插入。

行插入

将数据安全、容易地插入到 clickhouse 表的最安全、最简单的方式是使用 "writeRows" 方法。该方法将插入语句的前半部分作为第一个参数,将 PHP 数组作为行作为第二个参数。当插入数据时,"writeRows" 方法将数据编码成 Clickhouse 数据库可以解释的适当格式。默认格式是 JSON 格式。这种方法不需要显式转义。

# write data to a table
$client->writeRows('INSERT INTO myTable',
    [
        ['number' => 5],
        ['number' => 6],
        ['number' => 7]
    ]
);

文件插入

另一种插入数据的方式是从文件直接插入。

注意:文件中的数据格式应与 clickhouse 预期的格式匹配

$stream = fopen('my/local/file.lines.json','r');

$client->writeStream(
    'INSERT INTO t',
    $stream
);

此方法实际上不仅接受来自文件的数据,还接受任何php流资源的数据。因此,我们可以从其他地方导入数据,例如内存(或任何可以表示为流的东西)。

# create memory stream
$stream = fopen('php://memory','r+');
# write some data into it
fwrite($stream, '{"a":8}'.PHP_EOL.'{"a":9}'.PHP_EOL );
# rewind pointer to the beginning
rewind($stream);

# insert the data
$client->writeStream(
    'INSERT INTO t',
    $stream
);

系统查询

客户端对象支持系统查询。此类查询可以管理数据库模式、进程等。

# drop table
$client->system('DROP TABLE IF EXISTS t');
# create table
$client->system('CREATE TABLE IF NOT EXISTS t  (a UInt8) ENGINE = Memory');
# kill query
$client->system('KILL QUERY WHERE query_id = "SOME-QUERY-ID"');

如果在执行操作时失败,客户端将抛出异常。

还可以更改整个客户端的数据库。

# change database
$client->config()->change('database', 'new-database');

这使用与在“客户端”对象创建时传递的相同的配置对象,因此此代码也将有效。

# create config
$config = new Config();
# create client
$client = new Client($config);
# change database
$config->change('database', 'new-database');

格式

Clickhouse支持几种格式。这用于检索和插入数据。默认格式设置为JSON。当你执行简单的选择/插入查询时,数据将编码为JSON并在客户端与Clickhouse之间传输。这对于流/闭包查询/写入不适用。在执行任何查询/写入时,你可以通过传递类名作为最后一个参数来更改通信格式。

use ClickhouseClient\Client\Format;

# select using default JSON format
$client->query('SELECT * FROM system.numbers LIMIT 5');
# select using TabSeparated format
$client->query('SELECT * FROM system.numbers LIMIT 5', Format\TabSeparatedFormat::class);

# insert usin JSON format
$client->writeRows('INSERT INTO myTable',
    [
        ['number' => 5],
        ['number' => 6],
        ['number' => 7]
    ]
);
# insert usin TabSeparated format
$client->writeRows('INSERT INTO myTable',
    [
        ['number' => 5],
        ['number' => 6],
        ['number' => 7]
    ], 
    Format\TabSeparatedFormat::class
);

# create client with differrent default format
$client = new Client($config, Format\TabSeparatedFormat::class);
# create client without default format (which would result in errors in some cases)
$client = new Client($config, null);

Ping

Clickhouse数据库支持ping方法。

你可以使用客户端的ping方法来检查数据库是否正确响应。

$client->ping();

如果出现连接问题,将抛出异常。

异常处理

客户端类发出的任何请求都可能抛出异常。

在执行查询时检查异常是一种良好的做法。

use ClickhouseClient\Exception\Exception;

try {
    $client->ping();
} catch (Exception $ex) {
    # get configurations of the connector
    $ex->getConfig();
    # get repsonse 
    $ex->getResponse();
    # and get the message, ofc
    $ex->getMessage();
}

支持

如果库有任何问题,请在GitHub上创建一个问题,或通过电子邮件b.ozerkins@gmail.com联系。