MySQL查询优化:匹配单行后终止子查询以降低查询负载
钱包交易存在性查询的优化方案
原查询使用COUNT()统计符合条件的交易记录来判断存在性,会遍历所有匹配的行,当movements数据量较大时效率低下。以下是两种更高效的替代方案:
方案一:使用EXISTS子查询(最优选择)
EXISTS的特性是找到第一条匹配记录后立即终止查询,无需统计总数,完美匹配你的需求:
SELECT w.*, EXISTS(SELECT 1 FROM movements m WHERE m.wallet_id = w.id AND m.type = 'BUY') AS has_buy_movement, EXISTS(SELECT 1 FROM movements m WHERE m.wallet_id = w.id AND m.type = 'SELL') AS has_sell_movement FROM wallet w;
这里SELECT 1是数据库优化的常规写法,不需要返回实际字段值,仅用于判断是否存在匹配行,性能比SELECT id更轻量。
方案二:LEFT JOIN + GROUP BY聚合
如果后续需要扩展更多交易类型的判断,这种方式只需扫描一次movements表中目标类型的记录:
SELECT w.*, MAX(CASE WHEN m.type = 'BUY' THEN TRUE ELSE FALSE END) AS has_buy_movement, MAX(CASE WHEN m.type = 'SELL' THEN TRUE ELSE FALSE END) AS has_sell_movement FROM wallet w LEFT JOIN movements m ON w.id = m.wallet_id AND m.type IN ('BUY', 'SELL') GROUP BY w.id; -- 若数据库要求列出所有非聚合字段,需补充wallet表的其他字段,如w.name, w.balance等
通过MAX()聚合函数判断对应交易类型是否存在,只要有一条匹配记录就会返回TRUE。
关键性能优化:添加联合索引
无论使用哪种方案,都建议在movements表上创建联合索引,让查询直接定位到目标数据,避免全表扫描:
CREATE INDEX idx_movements_wallet_type ON movements(wallet_id, type);
内容的提问来源于stack exchange,提问作者Fabio Manniti
相关产品推荐
相关产品推荐

