SQL JOIN关联currencies_rates表查询rate报table is full错误排查
问题描述
我尝试通过JOIN语法从currencies_rates表中提取rate字段,但运行查询时抛出错误"[HY000][1114] The table '' is full",不清楚写法存在什么问题,相关查询语句如下:
SELECT game_id, u.country, COUNT(*) as count, SUM(IF(currency = 'EUR', (bet * cr.rate), bet)) as total_bets FROM games_stats INNER JOIN users u on games_stats.user_id = u.id JOIN currencies_rates cr ON cr.to = 'EUR' WHERE u.country IS NOT NULL GROUP BY game_id, user_id ORDER BY total_bets DESC;
涉及的相关表结构如下:
currencies_rates表:
games_stats表:
问题原因
- 核心错误:JOIN缺少两表关联条件,触发笛卡尔积导致数据量爆炸
关联currencies_rates表时,仅写了cr.to = 'EUR'的过滤条件,没有添加currencies_rates和games_stats的字段关联逻辑(正确逻辑应该是通过games_stats.currency = cr.from匹配对应货币对EUR的汇率)。这种写法会让两表结果做全量笛卡尔积:如果games_stats和users关联后有100万条数据,currencies_rates里to='EUR'的记录有30条,最终中间结果会直接膨胀到3000万条,数据量超过临时表内存/磁盘限制时就会抛出table is full错误。 - GROUP BY字段不匹配
SELECT子句中查询了u.country字段,但GROUP BY里仅写了game_id, user_id,如果数据库开启了ONLY_FULL_GROUP_BY模式,这个写法本身会直接抛出语法错误,最终统计结果也会不符合预期。
修正后的SQL
SELECT gs.game_id, u.country, COUNT(*) as count, SUM(IF(gs.currency = 'EUR', gs.bet, gs.bet * cr.rate)) as total_bets FROM games_stats gs INNER JOIN users u ON gs.user_id = u.id -- 补充关联逻辑:用统计表的货币字段匹配汇率表的源货币,同时限定目标货币为EUR INNER JOIN currencies_rates cr ON gs.currency = cr.`from` AND cr.`to` = 'EUR' WHERE u.country IS NOT NULL GROUP BY gs.game_id, u.country, -- 把SELECT中出现的非聚合字段加入GROUP BY gs.user_id ORDER BY total_bets DESC;
补充说明
- 多表关联时建议给所有表加简短别名,查询字段前加表前缀限定归属,避免字段歧义引发的报错。
from、to属于SQL保留字,作为字段名使用时建议用反引号包裹,避免SQL解析错误。- 如果修正关联逻辑后仍然出现
table is full错误,可以检查数据库临时表目录的磁盘剩余空间,适当调大tmp_table_size、max_heap_table_size参数的阈值,提升临时表可用内存上限。
内容的提问来源于stack exchange,提问作者Dmitry Ivanoff
相关产品推荐
相关产品推荐

