真实用上一篇撞爆内存的同一条大右表JOIN,把内存上限设到200MB,对比hash算法失败和grace_hash算法通过分桶真实成功完成的差异。
代码-- 上一篇验证过:这条JOIN默认(hash算法)真实要用约352MB内存 -- 本文把内存上限设到200MB,分别真实测hash和grace_hash两种算法 SELECT count() FROM demo.jleft INNER JOIN demo.jbig ON jleft.k=jbig.k SETTINGS join_algorithm='hash', max_memory_usage=200000000; SELECT count() FROM demo.jleft INNER JOIN demo.jbig ON jleft.k=jbig.k SETTINGS join_algorithm='grace_hash', max_memory_usage=200000000, grace_hash_join_initial_buckets=8;
join_algorithm='hash': → DB::Exception: Query memory limit exceeded: would use 357.25 MiB (attempt to allocate chunk of 257.50 MiB), maximum: 190.73 MiB: While executing FillingRightJoinSide. (MEMORY_LIMIT_EXCEEDED) ← 真实失败 join_algorithm='grace_hash': → 真实成功返回结果 memory_usage: 184297549 字节(约184MB) query_duration_ms: 210
同一条JOIN、同样500万行的大右表、同样200MB的内存上限,hash算法真实还是老样子要把整个右表一次性构建进内存(需要357MB,超限);grace_hash算法真实用不到200MB就跑完了整条查询。
每一步都是本文上面用真实两种JOIN算法跑出来的原始结果。
join_algorithm='hash' 与 'grace_hash'grace_hash_join_initial_buckets 分桶设置