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

优化按手机号分组获取最新对话的MAX()慢查询请求

按手机号分组获取最新对话的查询优化方案

原查询问题分析

原查询先对全表按phone分组取最大id,再在外层过滤chat、status、seller_id,相当于先处理全表数据再筛选,数据量过大导致查询缓慢。


优化方案

1. 提前过滤条件,缩小分组范围

将外层的过滤条件移到子查询中,让分组仅针对符合条件的数据,而非全表:

SELECT * 
FROM messages 
WHERE id IN (
    SELECT max(id) 
    FROM messages 
    WHERE chat = :ch AND status = :st AND seller_id = :seller
    GROUP BY phone
) 
ORDER BY created_at DESC

2. 创建针对性复合索引

创建包含过滤字段、分组字段、聚合字段的复合索引,让数据库无需全表扫描即可完成分组和筛选:

-- 基础优化索引
CREATE INDEX idx_messages_seller_chat_status_phone_id ON messages (seller_id, chat, status, phone, id);

索引顺序逻辑:先按高频过滤字段(seller_id、chat、status)快速筛选数据,再按phone分组,最后直接取最大id,避免回表查询。

如果created_at与id自增顺序完全一致(新消息id越大,created_at越晚),可追加created_at到索引末尾,消除排序阶段的文件排序:

-- 带排序优化的索引
CREATE INDEX idx_messages_seller_chat_status_phone_id_created ON messages (seller_id, chat, status, phone, id, created_at);

3. 改用JOIN替代IN子查询

MariaDB对IN子查询的优化效率通常不如JOIN,改用关联查询可提升执行效率:

SELECT m.*
FROM messages m
JOIN (
    SELECT max(id) AS max_id
    FROM messages
    WHERE chat = :ch AND status = :st AND seller_id = :seller
    GROUP BY phone
) t ON m.id = t.max_id
ORDER BY m.created_at DESC

4. 简化排序逻辑(可选)

若id为自增主键,且created_at随id递增,可直接按id DESC排序,避免对created_at的额外排序操作:

SELECT m.*
FROM messages m
JOIN (
    SELECT max(id) AS max_id
    FROM messages
    WHERE chat = :ch AND status = :st AND seller_id = :seller
    GROUP BY phone
) t ON m.id = t.max_id
ORDER BY m.id DESC

内容的提问来源于stack exchange,提问作者Ebrahim P. Leite

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 22:35:39