ClickHouse结合SQLAlchemy查询结果丢失两行问题排查
问题分析与解决方案
这事儿我之前碰到过类似的,结合你给出的版本信息(SQLAlchemy 1.3.11、ClickHouse 19.17.4.11),咱们来拆解下问题根源和解决办法:
核心原因
ClickHouse的Date类型底层是UInt16,有效日期范围是1970-01-01 到 2105-12-31(对应天数0到65535)。你插入的created值(11345678、13345678这类大数字)远远超出了这个范围,插入时会触发数值溢出,生成的日期超出了旧版本SQLAlchemy ClickHouse驱动的解析能力。旧驱动碰到这类无法解析的日期时,会直接丢弃对应行,导致你只拿到2条结果。
验证步骤
你可以在clickhouse-client里执行这条命令,看看实际存储的日期和对应的数值:
SELECT id, created, toUInt16(created) AS created_uint FROM test_table;
会发现超出范围的created值已经溢出,生成的日期(比如2086年及以后)是旧驱动处理不了的。
解决方案
方案1:修正Date类型的取值范围
确保插入的created值在ClickHouse Date类型的有效范围内(天数0到65535,对应1970-01-01至2105-12-31)。比如把原始数值转换为合法日期后再插入:
INSERT INTO test_table (id, created) VALUES (1, toDate('1991-09-08'));
方案2:升级依赖版本
旧版本的SQLAlchemy和ClickHouse驱动存在日期解析bug,升级到较新版本就能解决:
- 把SQLAlchemy升级到2.x稳定版
- 升级
clickhouse-driver(SQLAlchemy ClickHouse适配器依赖的驱动)到最新版
升级后重新运行Python脚本,应该就能拿到全部4行数据了。
方案3:修改字段类型
如果业务确实需要存储超出Date范围的日期,可以把created字段类型改成DateTime64或者String,避免数值溢出问题:
-- 已有表修改字段 ALTER TABLE test_table MODIFY COLUMN created DateTime64; -- 新建表时直接指定 CREATE TABLE test_table (id INTEGER, created DateTime64) ENGINE = MergeTree(created, (id), 8192);
内容的提问来源于stack exchange,提问作者sanyassh




