易君召
发布于 2026-08-30 / 作者:易君召 / 6 阅读
0

如何通过数据库优化提升网站速度

网站慢很大一部分瓶颈来自数据库:慢查询、索引失效、大表扫描、连接过多、IO 压力大。优化分为索引优化、SQL 语句优化、表结构设计、数据库配置、架构层优化、业务层规避六个层面。

一、索引优化(最高性价比)

索引本质是以空间换查询时间,不是越多越好。

  1. 给 WHERE、JOIN、ORDER BY、GROUP BY 字段建索引

    • 联合索引遵循最左前缀原则,把过滤性高的字段放前面。

    • 避免:select * from table where a=? and b=?,只给 b 建索引。

  2. 避免索引失效场景

    • 字段做运算、函数:where year(create_time)=2026 → 改成范围查询create_time between '2026‑01‑01' and '2026‑12‑31'

    • 隐式类型转换:字符串字段用数字查询,索引失效

    • like '%关键词' 前缀通配符不走 B + 树索引

    • or 两边字段只有一边有索引,容易失效

  3. 不要过度建索引 索引会减慢INSERT/UPDATE/DELETE,写频繁业务少建索引;单表索引建议控制在 5‑8 个以内。

  4. 覆盖索引 查询字段全部包含在索引里,不需要回表。

    -- 建立联合索引(name,phone)
    select name,phone from user where name='xxx';
    
  5. 使用explain分析执行计划 重点看:type尽量到ref/range,避免ALL全表扫描;rows扫描行数越小越好;Extra避免Using filesortUsing temporary

二、SQL 语句优化

  1. 拒绝 select *,只查询需要的字段,减少网络传输、内存占用。

  2. 分页大偏移量优化

-- 慢:偏移很大,扫描前面大量行
select * from article order by id limit 100000,10;

-- 优化:主键过滤
select * from article where id > 100000 order by id limit 10;
  1. 减少 join 数量,多表 join 会膨胀中间结果集;大表尽量不要 join 大表。

  2. 避免在循环里执行 SQL(N+1 问题),改成批量查询。

// 坏:循环查库
for(Long id:idList){ queryById(id); }
// 好:in批量一次查出
select * from user where id in (?,?,?)

in 集合不要过大,几千条以上拆分批次。

  1. 避免不必要排序、分组;尽量利用索引完成 order by、group by,避免Using filesort

  2. 事务不要写太大,大事务会锁表、长连接、回滚日志暴涨,拆分小事务。

三、表结构设计优化

  1. 字段类型尽量小

    • 能用int不用bigint;能用varchar(64)不用varchar(1000)

    • 时间优先datetime,不要字符串存时间;布尔用tinyint

  2. 大字段拆分 text、blob 大字段拆到独立副表,主表查询不加载大文本,减少内存 IO。

  3. 适度反范式:读多写少场景,冗余少量字段减少 join,牺牲一点一致性换查询速度。

  4. 大表做分表

    • 水平分表:按时间、用户 ID 哈希拆分,单表控制百万‑千万级别

    • 垂直分表:把低频大字段拆分出去

  5. 定时清理历史冷数据,避免表无限膨胀。

四、数据库配置优化(MySQL 示例)

需要结合服务器内存,不要盲目抄参数。

  1. innodb_buffer_pool_size:InnoDB 最重要参数,物理内存 50%‑70%,把热点数据放内存,减少磁盘 IO。

  2. join_buffer_sizesort_buffer_size:每个连接独立分配,不要设置过大,防止内存暴涨。

  3. 开启慢查询日志slow_query_log,捕获执行超过阈值(比如 1 秒)的 SQL,定位慢 SQL。

  4. 连接池:数据库连接不是越大越好,max_connections不要几千,一般几百足够;应用侧连接池(HikariCP)合理配置。

  5. innodb_flush_log_at_trx_commit:业务可接受短暂丢失可设为 2 提升写入性能,金融业务保持 1。

五、架构层面优化

  1. 读写分离 主库负责写,多个从库负责读;网站大部分是读请求,读流量分摊到从库。

  2. 引入缓存,减少数据库访问

    • Redis 缓存热点数据:首页、商品、配置、高频查询结果。

    • 缓存策略:缓存穿透、击穿、雪崩做好防护。

核心思想:能缓存就不去查 DB。

  1. 大查询、统计报表不要跑主库,走从库、OLAP 库。

  2. 分库分表:数据量亿级别以上,使用 Sharding‑JDBC 等中间件做分库分表。

  3. 适当使用搜索引擎(Elasticsearch):模糊搜索、全文检索不要丢给 MySQL。

六、业务与运维层面

  1. 定期分析慢 SQL,迭代优化,业务迭代很容易新增烂 SQL。

  2. 定期做表优化OPTIMIZE TABLE,整理碎片(InnoDB 慎用,会锁)。

  3. 避免高峰期做大表 DDL,大表改字段使用在线 DDL 工具。

  4. 监控数据库指标:QPS、TPS、慢查询数量、连接数、锁等待、磁盘 IO,提前发现瓶颈。

简单排查流程(网站变慢时)

  1. 打开慢查询日志,找到耗时最高 SQL

  2. explain看执行计划,判断是否全表扫描、索引失效

  3. 优先补索引、改写 SQL;SQL 改不动考虑加缓存

  4. 数据量过大:分表 / 读写分离;硬件瓶颈升级磁盘(SSD)

典型案例

网站首页加载慢,排查发现首页循环 N+1 查询,加上没有索引,单 SQL 扫描几十万行。 优化:批量查询 + 建立联合索引 + Redis 缓存首页数据,响应时间从 2‑3s 降到几十 ms。


本文原创作者:易君召,详见:https://www.yijunzhao.cn/authors/yijunzhao,转载请注明出处。

原文链接 https://www.yijunzhao.cn/archives/database-optimization-improve-website-speed-guide

欢迎访问 小易撩挨踢

https://www.yijunzhao.cn/