帝国 CMS 数据库索引优化
学完这篇,你能自己在帝国 CMS 上定位到拖慢网站的那几条 SQL,并用索引把它们从几秒压到几十毫秒。
第一步:先确认瓶颈真的在数据库
这一步要拿到证据,证明「慢」是数据库造成的,而不是 PHP 或网络。
登录服务器,编辑 MySQL 配置文件(Linux 通常是 /etc/my.cnf,宝塔面板在「数据库 → 配置修改」里也能改),在 [mysqld] 段加入:
slow_query_log = 1
long_query_time = 1
slow_query_log_file = /var/log/mysql-slow.log
改完执行 systemctl restart mysqld(或 service mysql restart)重启 MySQL。
注意:
long_query_time先设 1 秒,跑两三天看看。直接设 0.1 秒会记下大量正常查询,日志反而没法看。
第二步:从慢查询日志里挑出高频 SQL
这一步筛出「出现次数最多 + 耗时最长」的那几条,它们才是优化目标。
等日志攒够量后执行:
mysqldumpslow -s t -t 20 /var/log/mysql-slow.log
-s t 表示按总耗时排序,-t 20 表示只看前 20 条。帝国 CMS 站上出现频率最高的通常是这两类:
- 列表页:
SELECT id,title,newstime FROM phome_ecms_news WHERE classid IN (...) AND checked=1 ORDER BY newstime DESC LIMIT 0,20 - 搜索页:
... FROM phome_ecms_news_index WHERE keyboard LIKE '%关键词%'
第三步:用 EXPLAIN 判断缺哪个索引
这一步要看清 MySQL 到底走了什么索引、扫了多少行。
把慢查询复制到后台「系统 → 执行SQL语句」里,前面加 EXPLAIN 执行:
EXPLAIN SELECT id,title,newstime FROM phome_ecms_news
WHERE classid IN (1,2,3) AND checked=1 ORDER BY newstime DESC LIMIT 20;
重点看三列:
type:出现ALL就是全表扫描,必须处理;ref、range算合格。key:显示NULL说明没用上任何索引。rows:预估扫描行数,几十万行的表这里如果是六位数,就是它了。Extra:出现Using filesort表示排序没走索引。
注意:先确认表引擎。执行
SHOW TABLE STATUS LIKE 'phome_ecms_news';,看Engine列。帝国 CMS 7.5 默认建表可能是 MyISAM,索引加法的写法一样,但 MyISAM 拼的是key_buffer_size,InnoDB 拼的是innodb_buffer_pool_size,调优参数不同。
第四步:给核心表加联合索引
这一步直接把第三步发现的扫描行数降下来。
以默认前缀 phome_ 为例,执行:
ALTER TABLE phome_ecms_news
ADD INDEX idx_class_checked_time (classid, checked, newstime);
字段顺序不能换:等值条件 classid、checked 在前,排序字段 newstime 在后,这样 MySQL 能同时完成过滤和排序,Using filesort 会消失。
搜索页那张表用前缀索引,别用 LIKE '%词%' 那种全表扫:
ALTER TABLE phome_ecms_news_index ADD INDEX idx_title (title(30));
字段是 text 类型时,创建索引必须带长度,比如 title(30)。
phome_ecms_news_data_1 这张副表存正文,已经有主键 id,不要再给 content 加索引,会撑爆磁盘且毫无收益。
加完索引再跑一次同样的 EXPLAIN,rows 应该从六位数掉到三位数,Extra 里的 Using filesort 应该消失。
注意:索引不是越多越好。每加一个索引,后台发一篇稿就多一次写入开销。全站索引总数控制在每表 5 个以内,加之前先看
SHOW INDEX FROM phome_ecms_news;里是不是已经有重复字段的索引。
第五步:定期维护,别让索引失效
这一步保证优化效果能长期保持。
在 phpMyAdmin 里选中数据库 → 选中数据表 → 点「结构」标签 → 底部「索引」区可以查看和删除索引,比敲 SQL 直观。
每月执行一次:
ANALYZE TABLE phome_ecms_news;
OPTIMIZE TABLE phome_ecms_news;
ANALYZE 更新统计信息,让优化器选对索引;OPTIMIZE 回收删除数据留下的碎片。表大时 OPTIMIZE 会锁表,安排在凌晨访问低谷做。
另外,帝国 CMS 本身的静态化比任何索引都管用:后台「系统 → 数据更新 → 更新信息页地址」批量生成 HTML,让列表页和内容页直接由 Nginx 返回,数据库压力能下降一个量级。
小结
- 优化顺序是:开慢查询日志 →
mysqldumpslow -s t -t 20找高频 SQL →EXPLAIN看type/key/rows/Extra。 - 列表页索引写成
(classid, checked, newstime),等值字段在前、排序字段在后。 - 搜索字段用前缀索引
title(30),text类型必须带长度。 - 先
SHOW TABLE STATUS确认 MyISAM 还是 InnoDB,再决定调哪个缓存参数。 - 索引不宜多,每表 5 个以内,每月
ANALYZE+OPTIMIZE一次。
原文链接:https://www.gj0.com/thread-942.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。