select * 在大数据量下拖垮查询的主因是数据库返回冗余字段,导致网络传输、php内存解析和json序列化开销剧增;应只查必要字段、确保索引覆盖、拆分大文本字段,并采用游标分页、pdo异常模式、redis空值/随机过期防护等综合优化策略。

为什么 SELECT * 在大数据量下会拖垮 PHP 查询
不是因为 PHP 慢,而是数据库返回了大量无用字段,网络传输、PHP 内存解析、JSON 序列化全跟着膨胀。10 万行数据若每行多传 2KB 无关字段,光网络就多扛 200MB 流量,mysqli_fetch_all() 可能直接 OOM。
- 只查真正需要的字段:
SELECT id, name, status,别用SELECT * - 加
WHERE条件前先确认索引是否覆盖:用EXPLAIN SELECT ...看type是否为ref或range,避免ALL - 文本类字段(如
content、description)单独拆表或延迟加载,主表只留摘要
PHP 中如何安全实现分页而不崩库
用 LIMIT offset, size 查第 1000 页?MySQL 得先扫完前 10 万行,越往后越慢。真高并发时,OFFSET 是隐形杀手。
- 改用游标分页(cursor-based pagination):按
id > ? ORDER BY id ASC LIMIT 20,每次记下最后一条id作为下次起点 - 禁止用户手动输页码,前端只提供「下一页」按钮,后端校验
last_id是否真实存在且未被删除 - 如果必须支持跳页,把热门页(如前 50 页)结果缓存到 Redis,过期时间设短(如 60 秒),冷页走游标兜底
mysqli 和 PDO 在高并发查询中怎么选
两者性能差异微乎其微,但默认行为和错误处理影响稳定性。线上出问题时,PDO 默认静默失败,mysqli 更容易暴露连接中断等底层异常。
- 用
PDO必须显式开启异常模式:$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) - 用
mysqli推荐长连接(mysql://...改为mysqli://...并启用MYSQLI_OPT_CONNECT_TIMEOUT),避免频繁握手开销 - 批量读取优先用
mysqli_stmt::get_result()+fetch_all(MYSQLI_ASSOC),比逐行fetch_assoc()少 30%+ PHP 用户态调用
Redis 缓存穿透与雪崩在查询优化里怎么防
缓存只是加速手段,不是救命稻草。没做防护的缓存层,在秒杀或爬虫扫接口时,反而会把数据库打穿。
立即学习“PHP免费学习笔记(深入)”;
- 穿透:查一个数据库根本不存在的
user_id=999999999,缓存不命中 → 查库 → 查不到 → 不写缓存 → 下次还来。解决方案:对空结果也缓存(如SET user:999999999 "null" EX 60),并加随机过期时间防集中失效 - 雪崩:大量 key 同一时刻过期,请求直击 DB。用
EXPIRE时主动加 1–5 分钟随机偏移,或改用逻辑过期(value 内嵌expire_time字段,由业务判断是否刷新) - 别缓存「实时性要求高」的数据(如库存余额),缓存只用于「读多写少 + 允许短暂不一致」场景,比如用户资料、文章分类
真正卡住高并发查询的,往往不是 SQL 写得不够炫,而是没想清楚哪一层该承担什么压力——数据库只管强一致性,PHP 只管编排和降级,Redis 只管扛读流量。漏掉任意一环,优化就变成纸上谈兵。











