加索引后查询仍慢因可能触发filesort或temporary;需用explain分析执行计划,遵循最左前缀,避免索引列函数操作,分页改用游标或限制offset。

为什么加索引后查询还是慢?
不是所有字段加了索引就一定快。MySQL 在大表中执行 SELECT * 或含 ORDER BY、GROUP BY 的查询时,即使命中索引,也可能触发 Using filesort 或 Using temporary——这两类操作会把数据拉到磁盘临时文件处理,性能断崖下跌。
实操建议:
- 用
EXPLAIN看执行计划,重点检查type是否为range或更优(ref/eq_ref),避免ALL或index - 复合索引要遵循最左前缀原则:
WHERE a = ? AND b > ? ORDER BY c适合建(a, b, c),但(a, c, b)就无法支撑排序 - 避免在索引列上做函数操作,比如
WHERE YEAR(create_time) = 2024会让索引失效,改用create_time BETWEEN '2024-01-01' AND '2024-12-31'
分页查第100万条以后的数据怎么不卡死?
LIMIT 1000000, 20 这种写法会让 MySQL 扫描前 100 万行再丢弃,I/O 和 CPU 双重浪费。真实业务里,用户几乎不会翻到那么深的页,但接口没做限制就会被刷垮。
实操建议:
- 用游标分页(cursor-based pagination):记录上一页最后一条的
id或create_time,下一页查WHERE id > ? ORDER BY id LIMIT 20 - 如果必须用偏移量,给
LIMIT加硬限制,比如后端校验offset ,超限直接返回错误 - 对高偏移场景,可预生成分页映射表(如每天定时统计每万条的起始
id),用空间换时间
count(*) 为什么越来越慢?
MySQL 8.0 之前,MyISAM 表的 COUNT(*) 是 O(1),但 InnoDB 每次都得扫聚簇索引。表越大,扫描越久;加了 WHERE 条件后更没法走优化。
Shop7z网上购物系统支持电脑版+手机版+支付宝及微信支付,支持QQ和微信一键登陆,系统集众家之所长,大气超美观页面+手机版+商品组合套餐+限时抢购秒杀+图片批量上传+淘宝数据包导入+弹出式分类菜单+不同规格不同价格+新订单邮件通知+销售报表打印与Excel输出+物流跟踪打印查询+会员积分及优惠券+邮件群发+图片在线管理+销售统计报表+五种价格体系+礼品礼券+微信公众号支付+扫码支付等等等。
实操建议:
- 不要在实时接口里调
SELECT COUNT(*) FROM huge_table WHERE status = 1,改用近似值:查information_schema.TABLES的TABLE_ROWS(误差可能达 40%,但够看趋势) - 对精确计数需求,用汇总表:建一张
table_counts,每次增删时用事务同步更新对应status的计数 - 如果只是判断“有没有数据”,用
SELECT 1 FROM huge_table WHERE ... LIMIT 1,找到即停
大表 ALTER TABLE 怎么不锁表?
直接 ALTER TABLE huge_table ADD COLUMN x INT 在 MySQL 5.6+ 默认会重建表(copy 算法),期间 DML 阻塞,线上服务直接雪崩。
实操建议:
- 优先用
ALGORITHM=INPLACE支持的操作,例如加普通索引、改列默认值;执行前先查SHOW CREATE TABLE确认引擎是InnoDB - 对不支持 inplace 的变更(如加字段、改类型),用
pt-online-schema-change工具,它通过触发器双写+数据同步实现无锁 - 生产环境执行前,务必在从库上先试跑,观察
SHOW PROCESSLIST中是否出现长时间Waiting for table metadata lock
大表优化没有银弹。索引设计、分页逻辑、统计方式、DDL 策略,每个环节都可能成为瓶颈。最容易被忽略的是:没有定期清理历史数据,或者误信“等业务增长后再优化”的说法——等真到了千万级,很多架构决策已经没法回退了。









