从ClickHouse 18.16.0版本开始支持从HDFS的读文件,在 19.1.6 版本对HDFS访问功能进行了增强,支持读和写,在 19.4 版本以后开始支持Parquet格式。
本文介绍了如何从HDFS中读数据到ClickHouse中,测试版本为:19.4
在访问HDFS之前需要定义一个访问HDFS的表,指定表引擎为HDFS。表创建完成后,就可以对这张表进行查询。
查询CSV文件
例如,在HDFS上有一个数据文件:books.csv,内容如下:
hadoop fs -cat /user/hive/ck/book_csv/books.csv0553573403,book,A Game of Thrones,7.990553579908,book,A Clash of Kings,7.99055357342X,book,A Storm of Swords,7.990553293354,book,Foundation,7.990812521390,book,The Black Company,6.990812550706,book,Ender's Game,6.990441385532,book,Jhereg,7.950380014300,book,Nine Princes In Amber,6.990805080481,book,The Book of Three,5.99080508049X,book,The Black Cauldron,5.99
在ClickHouse上创建一个访问books.csv文件的表:
CREATE TABLE hdfs_books_csv(isbn String,cat String,name String,price Float64)ENGINE = HDFS('hdfs://host123:9000/user/hive/ck/book_csv/books.csv', 'CSV')
查询hdfs_books_csv表:
SELECT * FROM hdfs_books_csv┌─isbn───────┬─cat──┬─name──────────────────┬─price─┐│ 0553573403 │ book │ A Game of Thrones │ 7.99 ││ 0553579908 │ book │ A Clash of Kings │ 7.99 ││ 055357342X │ book │ A Storm of Swords │ 7.99 ││ 0553293354 │ book │ Foundation │ 7.99 ││ 0812521390 │ book │ The Black Company │ 6.99 ││ 0812550706 │ book │ Ender's Game │ 6.99 ││ 0441385532 │ book │ Jhereg │ 7.95 ││ 0380014300 │ book │ Nine Princes In Amber │ 6.99 ││ 0805080481 │ book │ The Book of Three │ 5.99 ││ 080508049X │ book │ The Black Cauldron │ 5.99 │└────────────┴──────┴───────────────────────┴───────┘
查询出的数据与books.csv的内容相同。
当用户执行 SELECT * FROM hdfs_books_csv 语句时,数据流向如下图:
这种使用场景相当于把HDFS做为ClickHouse的外部存储,需要查询数据时,直接访问HDFS的文件,而不需要把HDFS文件导入到ClickHouse,再进行查询。由于是从HDFS拉取数据,相对于ClickHouse的本地存储查询,速度较慢。
查询Parquet文件
ClickHouse 19.4 以后开始支持Parquet格式,下面对Parquet格式的HDFS数据文件进行测试,先上传一个Parquet数据文件:books.parquet 到HDFS,文件内容与books.csv相同,在HDFS上的路径如下:
/user/hive/ck/book_parquet/books.parquet
创建一个访问books.parquet文件的表:
CREATE TABLE hdfs_books_parquet(isbn String,cat String,name String,price Float64)ENGINE = HDFS('hdfs://host123:9000/user/hive/ck/book_parquet/books.parquet', 'Parquet')
在ClickHouse查询 hdfs_books_parquet 表:
SELECT * FROM hdfs_books_parquet┌─isbn───────┬─cat──┬─name──────────────────┬─price─┐│ 0553573403 │ book │ A Game of Thrones │ 7.99 ││ 0553579908 │ book │ A Clash of Kings │ 7.99 ││ 055357342X │ book │ A Storm of Swords │ 7.99 ││ 0553293354 │ book │ Foundation │ 7.99 ││ 0812521390 │ book │ The Black Company │ 6.99 ││ 0812550706 │ book │ Ender's Game │ 6.99 ││ 0441385532 │ book │ Jhereg │ 7.95 ││ 0380014300 │ book │ Nine Princes In Amber │ 6.99 ││ 0805080481 │ book │ The Book of Three │ 5.99 ││ 080508049X │ book │ The Black Cauldron │ 5.99 │└────────────┴──────┴───────────────────────┴───────┘
以上的表是从HDFS上直接查询数据,也可以将读取的数据加载到ClickHouse的本地表。
从HDFS导入数据
在ClickHouse先创建一个目标表,然后执行INSERT...SELECT导入数据。
CREATE TABLE books_local(isbn String,cat String,name String,price Float64)ENGINE = Log;INSERT INTO books_local SELECT * FROM hdfs_books_parquet;SELECT * FROM books_local;
更多的文件格式参见:https://clickhouse.yandex/docs/en/interfaces/formats/
总结
用户通过执行SQL语句,可以在ClickHouse中直接读取HDFS的文件,也可以将读取的数据导入到ClickHouse本地表。ClickHouse提供了对Hadoop生态圈更加友好的访问方式。
参考资料
https://github.com/yandex/ClickHouse/pull/3617/
https://github.com/yandex/ClickHouse/pull/4084/