MySQL分库分表后GROUP BY或SUM()需依赖中间件(如ShardingSphere)支持聚合下推,否则易因跨实例不支持、内存归并、路由失效等导致报错或结果错误。

分库分表后直接写 GROUP BY 或 SUM() 会报错或返回错误结果——MySQL 本身不支持跨物理实例的分布式聚合,必须靠外部机制协调。没有中间层兜底,应用层硬拼结果容易漏数据、丢精度、超时失败。
ShardingSphere 的 SELECT SUM() FROM t_order GROUP BY user_id 能否直接跑通?
能,但有前提:必须配置 sharding-algorithm 正确识别分片键,且聚合下推(push-down)开关打开。默认开启,但若 SQL 含子查询、UNION、窗口函数或非分片键上的 ORDER BY,它会退化为内存归并(memory merge),把所有分片结果拉到 JVM 里再算——数据量一过百万,OOM 风险极高。
- 检查
props.sql-show=true日志,确认每条实际下发到分库的 SQL 是否带GROUP BY和聚合函数;如果日志里只有SELECT *,说明没下推成功 - 避免在
SELECT列表中混用聚合字段和非分组普通字段(如SELECT user_id, SUM(money), name),这会强制走内存归并 - 分片键必须出现在
GROUP BY中,否则无法路由到具体分片,中间件会广播查询,性能雪崩
ClickHouse 做 MySQL 跨库聚合时,mysql 表引擎连接池怎么调?
ClickHouse 的 mysql 表引擎本质是 JDBC 客户端,每个 CREATE TABLE 对应一个独立连接。并发查多个 MySQL 分库时,连接数 = 分库数 × 查询并发数,很容易打满 MySQL 的 max_connections。
- 在 ClickHouse 的
config.xml中配<mysql_port>3306</mysql_port>同时加<mysql_max_connections>10</mysql_max_connections>,限制单个 MySQL 实例最大连接数 - 建表时显式指定
ENGINE = MySQL('host:port', 'db', 'table', 'user', 'pwd'),不要依赖全局用户配置,避免权限或连接复用冲突 - 聚合前先用
WHERE dt >= '2026-04-01'下推过滤,别让 ClickHouse 拉全量数据回来再GROUP BY
ETL 同步到 Hive/ClickHouse 后,COUNT(DISTINCT uid) 结果不准怎么办?
这是典型的数据倾斜 + 近似算法叠加导致的误差。Hive 默认用 ndv()(HyperLogLog),ClickHouse 用 uniq(),两者都是概率算法,误差率约 1%~2%。真实业务要求精确值时,必须绕开。
- ClickHouse 改用
count(distinctExact(uid)),代价是内存翻倍,单次查询超 1000 万 distinct 值可能 OOM - Hive 改用
count(distinct uid) + DISTRIBUTE BY uid + SORT BY uid强制 shuffle 均衡,但作业时间增加 3–5 倍 - 更稳的路:在 MySQL 分库各自算出
GROUP_CONCAT(DISTINCT uid),同步到汇总库后再用字符串去重合并——适合 uid 总量可控(比如千万级以内)
真正难的不是选哪种方案,而是分库键和业务聚合维度是否对齐。比如按 user_id 分库,却要按 region 统计销售额,这种场景无论中间件还是数仓,都得扫全库——索引和路由全部失效,只能接受“慢”这个事实。


















