the-tinderbox / clickhouse-php-client
基于HTTP的Clickhouse客户端
Requires
- php: ^7.1|^8.0
- guzzlehttp/guzzle: ^6.0|^7.0
Requires (Dev)
- mockery/mockery: ^0.9|^1.4
- php-coveralls/php-coveralls: ^2.2
- phpunit/phpcov: ^5.0|^6.0|^7.0|^8.0
- phpunit/phpunit: ^7.0|^8.0|^9.0
This package is auto-updated.
Last update: 2024-09-24 02:13:59 UTC
README
该包是为Clickhouse编写的客户端。
客户端使用Guzzle向Clickhouse服务器发送HTTP请求。
要求
php7.1
安装
Composer
composer require the-tinderbox/clickhouse-php-client
使用方法
客户端可以与单个服务器和集群一起工作。此外,客户端可以执行异步选择和插入(从本地文件)查询。
单机服务器
$server = new Tinderbox\Clickhouse\Server('127.0.0.1', '8123', 'default', 'user', 'pass'); $serverProvider = (new Tinderbox\Clickhouse\ServerProvider())->addServer($server); $client = new Tinderbox\Clickhouse\Client($serverProvider);
集群
$testCluster = new Tinderbox\Clickhouse\Cluster('cluster-name', [ 'server-1' => [ 'host' => '127.0.0.1', 'port' => '8123', 'database' => 'default', 'user' => 'user', 'password' => 'pass' ], 'server-2' => new Tinderbox\Clickhouse\Server('127.0.0.1', '8124', 'default', 'user', 'pass') ]); $anotherCluster = new Tinderbox\Clickhouse\Cluster('cluster-name', [ [ 'host' => '127.0.0.1', 'port' => '8125', 'database' => 'default', 'user' => 'user', 'password' => 'pass' ], new Tinderbox\Clickhouse\Server('127.0.0.1', '8126', 'default', 'user', 'pass') ]); $serverProvider = (new Tinderbox\Clickhouse\ServerProvider())->addCluster($testCluster)->addCluster($anotherCluster); $client = (new Tinderbox\Clickhouse\Client($serverProvider));
在集群上执行任何查询之前,您应该提供集群名称,客户端将在指定的集群上运行所有查询。
$client->onCluster('test-cluster');
默认情况下,客户端将使用服务器列表中的随机服务器或指定的集群。如果您想对指定的服务器执行请求,您应该使用客户端上的using($hostname)
方法,然后运行查询。客户端将记住主机名以供后续查询使用。
$client->using('server-2')->select('select * from table');
服务器标签
$firstServerOptionsWithTag = (new \Tinderbox\Clickhouse\Common\ServerOptions())->setTag('tag'); $secondServerOptionsWithAnotherTag = (new \Tinderbox\Clickhouse\Common\ServerOptions())->setTag('another-tag'); $server = new Tinderbox\Clickhouse\Server('127.0.0.1', '8123', 'default', 'user', 'pass', $firstServerOptionsWithTag); $cluster = new Tinderbox\Clickhouse\Cluster('cluster', [ new Tinderbox\Clickhouse\Server('127.0.0.2', '8123', 'default', 'user', 'pass', $secondServerOptionsWithAnotherTag) ]); $serverProvider = (new Tinderbox\Clickhouse\ServerProvider())->addServer($server)->addCluster($cluster); $client = (new Tinderbox\Clickhouse\Client($serverProvider));
要使用带有标签的服务器,您应该在执行任何查询之前调用usingServerWithTag
函数。
$client->usingServerWithTag('tag');
选择查询
任何SELECT查询都将返回Result
的实例。该类实现了\ArrayAccess
、\Countable
和\Iterator
接口,这意味着它可以作为数组使用。
可以通过rows
属性获取结果行数组
$rows = $result->rows; $rows = $result->getRows();
您还可以获取查询执行的某些统计信息
- 读取的行数
- 读取的字节数
- 查询执行时间
- 至少在限制之前的行数
可以通过statistic
属性获取统计信息
$statistic = $result->statistic; $statistic = $result->getStatistic(); echo $statistic->rows; echo $statistic->getRows(); echo $statistic->bytes; echo $statistic->getBytes(); echo $statistic->time; echo $statistic->getTime(); echo $statistic->rowsBeforeLimitAtLeast; echo $statistic->getRowsBeforeLimitAtLeast();
同步
$result = $client->readOne('select number from system.numbers limit 100'); foreach ($result as $number) { echo $number['number'].PHP_EOL; }
使用本地文件
您可以将本地文件用作Clickhouse中的临时表。您应该将TempTable
实例数组作为第三个参数传递。
在这种情况下,将从服务器发送一个文件,Clickhouse将从该文件中提取数据到临时表中。表的结构为:
- number - UInt64
如果您将这样的数组作为结构传递
['UInt64']
则文件中的每个列将被命名为 _1、_2、_3。
$result = $client->readOne('select number from system.numbers where number in _numbers limit 100', new TempTable('_numbers', 'numbers.csv', [ 'number' => 'UInt64' ])); foreach ($result as $number) { echo $number['number'].PHP_EOL; }
您可以提供文件的路径或将FileInterface
实例作为第二个参数传递。
有一些其他类型的文件流可以用于发送到服务器
- 文件 - 存储在磁盘上的简单文件;
- FileFromString - 从字符串创建的流。例如:
new FileFromString('1'.PHP_EOL.'2'.PHP_EOL.'3'.PHP_EOL)
- MergedFiles - 包含多个文件并将它们合并成一个流的流。您应该将包含应合并到一个流中的文件路径列表传递给构造函数。
- TempTable -
FileInterface
实例的包装器,包含结构。用于使用MergedFiles
进行插入。
异步
与返回Result
的readOne
方法不同,read
方法为每个执行的查询返回一个Result
数组。
list($clicks, $visits, $views) = $client->read([ ['query' => "select * from clicks where date = '2017-01-01'"], ['query' => "select * from visits where date = '2017-01-01'"], ['query' => "select * from views where date = '2017-01-01'"], ]); foreach ($clicks as $click) { echo $click['date'].PHP_EOL; }
在read
方法中,您可以传递参数$concurrency
,它负责最大并发请求数量。
使用本地文件
与同步选择请求一样,您可以将文件传递到服务器
list($clicks, $visits, $views) = $client->read([ ['query' => "select * from clicks where date = '2017-01-01' and userId in _users", new TempTable('_users', 'users.csv', ['number' => 'UInt64'])], ['query' => "select * from visits where date = '2017-01-01'"], ['query' => "select * from views where date = '2017-01-01'"], ]); foreach ($clicks as $click) { echo $click['date'].PHP_EOL; }
在异步请求中,您可以像同步请求一样传递多个文件
插入查询
插入查询始终返回true或错误时抛出异常。
数据可以逐行写入或从本地的CSV或TSV文件中写入。
$client->writeOne("insert into table (date, column) values ('2017-01-01',1), ('2017-01-02',2)"); $client->write([ ['query' => "insert into table (date, column) values ('2017-01-01',1), ('2017-01-02',2)"], ['query' => "insert into table (date, column) values ('2017-01-01',1), ('2017-01-02',2)"], ['query' => "insert into table (date, column) values ('2017-01-01',1), ('2017-01-02',2)"] ]); $client->writeFiles('table', ['date', 'column'], [ new Tinderbox\Clickhouse\Common\File('/file-1.csv'), new Tinderbox\Clickhouse\Common\File('/file-2.csv') ]); $client->insertFiles('table', ['date', 'column'], [ new Tinderbox\Clickhouse\Common\File('/file-1.tsv'), new Tinderbox\Clickhouse\Common\File('/file-2.tsv') ], Tinderbox\Clickhouse\Common\Format::TSV);
在执行 writeFiles
查询时异步执行。如果您有很多文件并且希望在一次插入查询中插入它们,可以使用我们的 ccat
工具和 MergedFiles
实例来代替 File
。您应将插入文件的列表放入一个文件中。
file-1.tsv
file-2.tsv
构建 ccat
ccat
源代码放置在 utils/ccat
目录中。只需运行 make && make install
即可构建并安装库到包的 bin
目录。在 bin
目录中已经有编译好的 ccat
二进制文件,但它可能在某些系统上无法正常工作。
在 writeFiles
方法中,您可以传递参数 $concurrency
,它负责最大同时请求数量。
其他查询
除了 SELECT 和 INSERT 查询之外,您还可以执行其他查询 :) 有一个 statement
方法用于此目的。
$client->writeOne('DROP TABLE table');
测试
$ composer test
路线图
- 添加将查询结果保存到本地文件的能力
贡献
请发送您的拉取请求,并提出如何改进任何内容的建议。我们将非常感激。
谢谢!