全部
常见问题
产品动态
精选推荐

(200w 用户列表页面卡顿)是大多数中大型系统后台的通病

管理 管理 编辑 删除

我们可以通过 分页 + 缓存 + 异步统计 来完美解决。

非常好 👍 你这个需求(200w 用户列表页面卡顿)是大多数中大型系统后台的通病,我们可以通过 分页 + 缓存 + 异步统计 来完美解决。

下面我给出完整方案,分为 架构思路 → SQL 优化 → 缓存方案 → ThinkPHP 示例代码 四个部分,拿去直接可落地用。👇


一、架构思路(核心目标)

模块优化目标说明
分页查询秒级打开只查询 20 条数据,不做复杂统计
总数统计缓存或异步更新避免每次执行 COUNT(200w)
搜索 / 筛选可索引字段查询避免模糊 LIKE + JOIN
JOIN 数据最小化尽量只在必要字段时再 JOIN


二、数据库设计与索引优化

1️⃣ 关键索引

ALTER TABLE eb_user ADD PRIMARY KEY (uid);
ALTER TABLE eb_user ADD INDEX idx_created_at(created_at);
ALTER TABLE eb_wechat_user ADD INDEX idx_uid(uid);
uid 是主键; created_at 用于分页排序; JOIN 用的字段必须有索引。


三、分页 + 异步统计方案

方案目标

  1. 列表页加载快(1 秒内)
  2. 总数、搜索、统计延迟可接受(几分钟内更新)


1. 用户列表分页 SQL(高效版)

SELECT 
  u.uid,
  u.nickname,
  u.phone,
  w.openid,
  w.subscribe
FROM eb_user u
LEFT JOIN eb_wechat_user w ON u.uid = w.uid
ORDER BY u.created_at DESC
LIMIT 0, 20;
  • 避免在分页时使用 COUNT(*)。
  • 用索引字段排序(created_at 或 uid)。


2. 用户总数统计缓存表

新建一个缓存表:

CREATE TABLE sys_stat_cache (
  id INT PRIMARY KEY AUTO_INCREMENT,
  stat_key VARCHAR(64) UNIQUE,
  stat_value BIGINT,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

初始化:

INSERT INTO sys_stat_cache (stat_key, stat_value) VALUES ('user_total', 0);


3. 定时任务更新用户总数

用一个后端定时脚本(如 ThinkPHP 命令行任务):

<?php
namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Db;

class UpdateUserCount extends Command
{
    protected function configure()
    {
        $this->setName('update:usercount')
             ->setDescription('更新用户总数缓存');
    }

    protected function execute(Input $input, Output $output)
    {
        $count = Db::name('eb_user')->count();
        Db::name('sys_stat_cache')
            ->where('stat_key', 'user_total')
            ->update(['stat_value' => $count]);
        $output->writeln("User total updated: {$count}");
    }
}

建议执行周期:

  • 每 5 分钟一次(用 crontab 或队列触发)
  • 对 200w 用户表,这种 COUNT 操作耗时 2~5 秒,完全可以后台运行。


4. 后台控制器读取缓存统计

// app/admin/controller/UserController.php

use think\facade\Db;

public function index()
{
    // 分页参数
    $page = input('page', 1);
    $limit = input('limit', 20);
    $offset = ($page - 1) * $limit;

    // 快速分页查询
    $list = Db::name('eb_user')
        ->alias('u')
        ->leftJoin('eb_wechat_user w', 'u.uid=w.uid')
        ->field('u.uid,u.nickname,u.phone,w.openid,w.subscribe')
        ->order('u.created_at desc')
        ->limit($offset, $limit)
        ->select();

    // 从缓存表读取总数
    $total = Db::name('sys_stat_cache')
        ->where('stat_key', 'user_total')
        ->value('stat_value');

    return json([
        'code' => 0,
        'data' => [
            'list'  => $list,
            'total' => $total
        ]
    ]);
}

效果:

  • 查询 20 条记录:< 0.5 秒
  • 总数从缓存表读取:< 1 毫秒 ✅ 后台页面可秒开


5. 可选 Redis 缓存(更快)

如果系统已经使用 Redis,可以直接:

// 写缓存
$count = Db::name('eb_user')->count();
cache('user_total', $count, 300); // 缓存 5 分钟

// 读缓存
$total = cache('user_total');
Redis 读取速度约 0.2ms,比数据库缓存表还快。


四、整体流程图

┌────────────┐
│ 前端请求用户列表 │
└──────┬─────┘
       │
       ▼
┌─────────────────────────────┐
│ 控制器从 sys_stat_cache 取总数 │  ← (0.001s)
│ 并分页查询用户表 + 关联表       │  ← (0.5s)
└─────────────────────────────┘
       │
       ▼
┌──────────────────────────┐
│ 定时任务每5分钟更新缓存 │ ← (后台执行)
└──────────────────────────┘


五、最终效果与性能提升对比

操作原始方案优化后
后台列表打开30+ 秒< 1 秒
总数统计实时 COUNT(200w)缓存读取
系统负载稳定
可扩展性优秀,可扩展到千万级


可扩展方向(后续升级)

  1. 用户表分表:按注册时间或地区水平分表。
  2. 搜索索引引擎:用 Elasticsearch / Sphinx 替代复杂 LIKE 查询。
  3. 数据异步聚合:用消息队列异步写入统计缓存。
  4. MySQL 8.0 并行查询优化:利用窗口函数或 JSON 聚合简化多表 JOIN。



请登录后查看

小码二开 最后编辑于2025-10-24 10:07:36

快捷回复
回复
回复
回复({{post_count}}) {{!is_user ? '我的回复' :'全部回复'}}
排序 默认正序 回复倒序 点赞倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level || item.bbs_level }}

作者 管理员 企业

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推荐': '推荐'}}
{{item.is_suggest == 1? '取消推荐': '推荐'}} 【已收集】
沙发 板凳 地板 {{item.floor}}# 【已收集】
{{item.user_info.title || '暂无简介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打赏
已打赏¥{{item.reward_price}}
{{item.like_count}}
{{item.showReply ? '取消回复' : '回复'}}
删除
回复
回复

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回复 {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打赏
已打赏¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回复' : '回复'}}
删除
回复
回复
查看更多
打赏
已打赏¥{{reward_price}}
43
{{like_count}}
{{collect_count}}
添加回复 ({{post_count}})

相关推荐

快速安全登录

使用微信扫码登录
{{item.label}} 加精
{{item.label}} {{item.label}} 板块推荐 常见问题 产品动态 精选推荐 首页头条 首页动态 首页推荐
取 消 确 定
回复
回复
问题:
问题自动获取的帖子内容,不准确时需要手动修改. [获取答案]
答案:
提交
bug 需求 取 消 确 定
打赏金额
当前余额:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
请输入 0.1-{{reward_max_price}} 范围内的数值
打赏成功
¥{{price}}
完成 确认打赏

微信登录/注册

切换手机号登录

{{ bind_phone ? '绑定手机' : '手机登录'}}

{{codeText}}
切换微信登录/注册
暂不绑定
CRMEB客服

CRMEB咨询热线 咨询热线

400-8888-794

微信扫码咨询

CRMEB开源商城下载 源码下载 CRMEB帮助文档 帮助文档
返回顶部 返回顶部
CRMEB客服