thinkphp数据库查询慢的根源不在缓存残留,而在缓存未生效、sql未走索引或驱动配置错误;需验证model_cache.php是否存在、检查[ cache hit ]标识、确认cache()键含全部变量、驱动是否为redis、索引是否建立及explain中type是否为all。

ThinkPHP数据库缓存清理后查询依然慢,说明问题不在缓存残留,而是缓存根本没生效、SQL未走索引、或底层驱动配置错误——必须跳过“再清一次缓存”的惯性操作,直击真实瓶颈。
确认模型查询缓存是否真正启动
执行php think optimize:schema命令,检查runtime/cache/目录下是否存在model_cache.php文件——【没有该文件说明模型缓存根本未启动】。
在控制器中插入调试语句:dump(Db::getLastSql());后紧跟select()调用,观察日志里是否出现“[CACHE HIT]”标识;若无,则当前查询未命中缓存,别急着优化SQL,先回头检查cache()调用位置。
运行php think cache:clear --tag=model,再刷新接口,对比两次X-Response-Time响应头数值变化;下降超过150ms才表明缓存已介入。
禁用cache(true)并改用带参缓存键
第一步:全局搜索项目中所有cache(true),全部替换为含参数组形式。cache(true)只对完全静态的find(1)类查询安全,其余场景一律失效。
第二步:将影响结果的所有变量打包进数组作为缓存键,例如cache(['user_list', $status, $type, $page], 600)。TP会自动序列化并md5生成唯一键,避免字符串拼接导致的类型歧义(比如$status=1和$status='1'被识别为不同键)。
第三步:关联查询需单独缓存,在关联定义方法内显式加cache(),例如:return $this->hasOne(Profile::class)->cache(['profile', $this->id], 3600);。注意:如果主模型用了软删除但缓存键未包含delete_time字段,逻辑删除后仍返回旧数据——【必须把delete_time也塞进缓存键数组】。
检查缓存驱动是否为Redis
打开config/cache.php,确认'default'值不是'file'而是'redis'。
若仍用file驱动,同一台服务器多进程并发写缓存文件会触发锁等待,响应时间波动剧烈。
验证Redis连接是否正常:在控制器中执行Cache::store('redis')->set('test_key', 'ok', 10),再get('test_key')能取回值才算通。
排查SQL是否走了索引
方法一:用SHOW INDEX FROM user检查常用查询字段(如mobile、status)是否在索引列表里;若没有,执行ALTER TABLE user ADD INDEX idx_mobile (mobile);。
方法二:对复合查询优先建联合索引,顺序按「等值条件在前、范围条件在后」,例如ADD INDEX idx_status_created (status, created_at);。
方法三:避免对索引字段做函数操作,比如where('DATE(created_at)', '2024-01-01')会让索引失效,应改用whereBetween('created_at', [$start, $end])。
开启'sql_explain' => true加到数据库配置里,会自动对每条SELECT执行EXPLAIN并打印;关键看type字段:出现ALL就是全表扫描,range或ref才算走了索引。
启用字段缓存并关闭严格检查
在config/database.php中设置'fields_cache' => true,减少元数据查询开销。
将'fields_strict' => false,避免不必要的字段验证拖慢ORM解析。
同时确认'break_reconnect' => true已开启,防止短时网络抖动引发连接中断重试延迟。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











