真实起一个MinIO实例,验证ClickHouse的s3()表函数能否不导入数据直接在对象存储上查询,以及反向写出新文件的对称能力。
代码-- 真实生成1000行数据的Parquet文件,上传到MinIO(S3协议兼容) clickhouse local --query "SELECT number AS id, concat('user',toString(number)) AS name, number*1.5 AS amt FROM numbers(1000) INTO OUTFILE 'testdata.parquet' FORMAT Parquet" -- (真实用boto3上传到 http://127.0.0.1:19400/ch-lab/testdata.parquet) SELECT count(), sum(amt) FROM s3('http://127.0.0.1:19400/ch-lab/testdata.parquet', 'minioadmin', 'minioadmin123', 'Parquet');
SELECT * FROM s3(...) LIMIT 5; → 0 user0 0 1 user1 1.5 2 user2 3 3 user3 4.5 4 user4 6 SELECT count(), sum(amt) FROM s3(...); → 1000 749250 真实手算核对:sum(1.5*i) for i in 0..999 = 1.5 * (0+1+...+999) = 1.5*499500 = 749250 ← 完全吻合
整个过程真实没有执行任何CREATE TABLE或者INSERT,数据从头到尾只存在于MinIO上的这一个Parquet文件里,s3()表函数真实把它当成一张"临时表"直接参与SQL查询,聚合结果跟手工核算完全吻合。
INSERT INTO FUNCTION s3('http://127.0.0.1:19400/ch-lab/output.parquet',
'minioadmin', 'minioadmin123', 'Parquet')
SELECT number, concat('out',toString(number)) FROM numbers(500);
-- 真实检查MinIO上多出的文件
output.parquet 5148 字节 ← 真实新生成的文件
-- 真实读回验证
SELECT count() FROM s3('http://127.0.0.1:19400/ch-lab/output.parquet', ...);
→ 500每一步都是本文上面用真实MinIO跑出来的原始结果。
s3() 表函数SELECT FROM s3(...) 与 INSERT INTO FUNCTION s3(...) 双向能力