You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL查询优化请求:获取关注用户谱面的查询耗时超6秒

优化你的Beatmap查询性能

咱们先拆解下你当前查询慢的核心原因:关联子查询的重复执行、GROUP BY可能触发的临时表/文件排序,以及缺少合适索引导致的全表扫描。下面是针对性的优化方案:

1. 优先优化索引(最核心的一步)

索引是提升查询速度的关键,针对你的查询场景,建议创建以下两个复合索引:

  • 针对follows表:
    你的查询需要过滤follows.uid = 3443963,并关联follows.fid = maps.uid,创建复合索引可以让数据库快速定位匹配行,无需全表扫描:

    CREATE INDEX idx_follows_uid_fid ON follows (uid, fid);
    

    如果想实现覆盖查询(不用回表取follows.id),可以把id也加入索引:

    CREATE INDEX idx_follows_uid_fid_id ON follows (uid, fid, id);
    
  • 针对maps表:
    你的查询需要按sid分组找最新的add_time,同时过滤特定uid的记录,创建包含uid、sid、add_time的复合索引,能让数据库快速过滤并排序:

    CREATE INDEX idx_maps_uid_sid_addtime ON maps (uid, sid, add_time DESC);
    

    这个索引可以同时满足:过滤关注用户的maps、按sid分组取最新时间、最终排序的需求。

2. 重写查询,用窗口函数替代关联子查询+GROUP BY

原来的关联子查询(SELECT max(add_time) FROM maps i WHERE i.sid = maps.sid)会对主查询的每一行执行一次,非常低效。改用窗口函数可以一次性完成分组取最新记录的操作:

SELECT 
    m.id as mapid,
    m.uid,
    m.add_time,
    -- 只选你实际需要的字段,别用SELECT *,减少数据传输和索引回表
    m.sid
    -- 其他你需要的字段...
FROM (
    SELECT 
        *,
        -- 按sid分组,给每条记录按add_time降序排号,最新的那条行号为1
        ROW_NUMBER() OVER (PARTITION BY sid ORDER BY add_time DESC) as rn
    FROM maps
    -- 先获取所有关注用户的ID,过滤maps的uid
    WHERE uid IN (SELECT fid FROM follows WHERE uid = 3443963)
      AND uid != 3443963
) m
WHERE m.rn = 1
ORDER BY m.add_time DESC
LIMIT 9;

这种写法的优势:

  • 只扫描maps表一次,避免了关联子查询的重复执行
  • 用ROW_NUMBER()替代GROUP BY,避免了临时表和文件排序的开销
  • 逻辑更清晰,也符合现代SQL的最佳实践

3. 简化JOIN逻辑

你原来用LEFT JOIN然后WHERE follows.id IS NOT NULL,这其实等价于INNER JOIN——因为LEFT JOIN保留的不匹配行都会被WHERE条件过滤掉。改成INNER JOIN能让数据库优化器生成更高效的执行计划:

如果坚持用原来的JOIN写法,可以改成:

SELECT 
    -- 只选需要的字段
    m.id as mapid,
    m.uid,
    m.add_time,
    m.sid
FROM maps m
INNER JOIN follows f 
    ON f.fid = m.uid 
    AND f.uid = 3443963
WHERE m.uid != 3443963
  AND m.add_time = (SELECT MAX(add_time) FROM maps i WHERE i.sid = m.sid)
GROUP BY m.sid
ORDER BY m.add_time DESC
LIMIT 9;

4. 额外小技巧

  • 避免SELECT *:只选择你实际需要的字段,这样如果索引包含这些字段,数据库可以直接从索引取数据(覆盖索引),不用回表查询原数据,速度会快很多。
  • 查看执行计划:用EXPLAIN命令查看你的查询执行计划,看看是否有Using filesort、Using temporary或者ALL(全表扫描)的标记,这些都是需要优化的点。

内容的提问来源于stack exchange,提问作者Daniel Yeffet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:27:24