赞片CMSMySQL优化
照着做完,你能把赞片CMS 的 MySQL 从"每个页面都慢半拍"调到"打开列表页基本不查库"。
赞片CMS 是基于 ThinkPHP 3.2 的影视站程序,天生读多写少:一次列表页请求可能扫十几万行 zp_vod 表。所以优化思路不是"加机器",而是先定位慢查询 → 调 MySQL 参数 → 补索引 → 砍掉没用的查询。下面按顺序来。
第一步:开慢查询日志,先找出到底哪条 SQL 慢
这一步要拿到"实际执行超过 1 秒的 SQL 清单",不然所有调优都是瞎猜。
登录服务器后连上 MySQL:
mysql -uroot -p
在 MySQL 命令行里临时开启(重启失效,用来验证):
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = ON;
SHOW VARIABLES LIKE 'slow_query_log_file';
永久生效改配置文件。宝塔面板用户走:软件商店 → MySQL 5.7 → 设置 → 配置修改,在 [mysqld] 段落下加:
slow_query_log = 1
slow_query_log_file = /www/server/data/mysql-slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
保存后点同页面的「重启」,或命令行 systemctl restart mysqld。
跑半小时真实流量,然后看日志:
mysqldumpslow -s t -t 20 /www/server/data/mysql-slow.log
-s t 按总耗时排序,前 20 条就是你的重点。
注意:
log_queries_not_using_indexes在写入频繁的站点会撑爆日志文件,定位完就把它关掉(设为 0)。
第二步:按机器内存调 my.cnf 核心参数
这一步做完,InnoDB 的读操作大部分会命中内存,磁盘 IO 直接降一个量级。
还是软件商店 → MySQL → 设置 → 配置修改,按下表改(以 8G 内存服务器为例):
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 4
innodb_flush_log_at_trx_commit = 2
innodb_log_file_size = 256M
innodb_io_capacity = 2000
max_connections = 300
table_open_cache = 2000
tmp_table_size = 64M
max_heap_table_size = 64M
query_cache_type = 0
query_cache_size = 0
几个关键点:
innodb_buffer_pool_size给物理内存的 50%~60%,这是最值钱的一个参数,别给超过 70%,要给 PHP 留内存。innodb_flush_log_at_trx_commit = 2把每次事务刷盘改成每秒刷一次,影视站丢一两秒数据无所谓,但写入速度能快好几倍。- MySQL 5.7 的
query_cache在高并发下是全局锁,必须关;MySQL 8.0 已经移除该参数,不用管。
改完重启 MySQL。
注意:
innodb_log_file_size改大后如果启动失败,是旧的 ib_logfile 大小不匹配,删掉/www/server/data/ib_logfile0和ib_logfile1再启动(务必先备份数据库)。
第三步:给赞片CMS 的 vod 表补索引
这一步的目标是让列表页的"按分类 + 按时间排序"从全表扫描变成索引扫描。
先确认表前缀,默认是 zp_,不确定就在 phpMyAdmin 里点开数据库看一眼,或执行:
SHOW TABLES LIKE '%vod%';
用 EXPLAIN 看典型查询:
EXPLAIN SELECT * FROM zp_vod WHERE vod_type_id = 12 ORDER BY vod_time DESC LIMIT 20;
如果 type 列是 ALL,加联合索引:
ALTER TABLE zp_vod ADD INDEX idx_type_time (vod_type_id, vod_time);
ALTER TABLE zp_vod ADD INDEX idx_letter (vod_letter);
ALTER TABLE zp_vod ADD INDEX idx_name (vod_name(30));
再加索引后重新 EXPLAIN,type 应该变成 ref 或 range,rows 从六位数降到两位数。
注意:索引不是越多越好,每个索引都会拖慢写入。加完用
SHOW INDEX FROM zp_vod;复查一遍,重复或从不被用到的索引(比如vod_id之外还单加vod_type_id)直接DROP INDEX掉。
第四步:清掉垃圾数据并回收空间
这一步能立刻减小表体积,让上面的索引更容易常驻内存。
影视站的播放记录、搜索记录、采集临时表往往涨到几百万行却没人看。在宝塔 phpMyAdmin 里执行:
TRUNCATE TABLE zp_search_log;
TRUNCATE TABLE zp_play_log;
(表名以你站点实际为准,先用 SHOW TABLES; 列出来。)
删完大表后回收文件空间:
OPTIMIZE TABLE zp_vod;
也可以在宝塔 phpMyAdmin 里勾选表 → 底部「选中项」下拉 → 优化表。
注意:
OPTIMIZE TABLE会锁表,影视站晚高峰别做,放到凌晨 3 点后,或者写进宝塔的「计划任务 → 数据库备份」之后执行。
第五步:开启缓存,让大部分请求根本不碰数据库
这一步是收益最大的——前面都是让查询变快,这一步是让查询消失。
进赞片CMS 后台 → 系统 → 性能优化(部分版本叫「缓存设置」),打开:
- 数据缓存:开启,缓存时间设 3600 秒
- HTML 静态缓存:列表页和详情页都勾上
如果服务器装了 Redis,在宝塔 软件商店 → Redis → 设置 确认已启动,然后编辑赞片CMS 的数据库配置文件(ThinkPHP 3.2 一般在 Application/Common/Conf/config.php,找不到就执行):
grep -rn "DATA_CACHE_TYPE" /www/wwwroot/你的站点目录 --include="*.php"
把 DATA_CACHE_TYPE 改成 Redis,填上 Redis 的 127.0.0.1:6379。
改完清一次缓存:后台 → 系统 → 更新缓存。
注意:开了静态缓存后,新采集的影片不会立刻显示,需要手动「更新缓存」或等缓存过期。采集频繁的时段可以先临时关掉。
小结
- 优化顺序固定:先开慢查询日志定位 → 再调 my.cnf → 再补索引 → 最后上缓存,跳步会白忙。
innodb_buffer_pool_size设成物理内存的 50%~60%,是单点收益最高的参数。- MySQL 5.7 的 query_cache 必须关闭,8.0 直接用默认值。
- 赞片CMS 的
zp_vod表加(vod_type_id, vod_time)联合索引,列表页立刻见效。 - 索引复查一遍,多余的删掉,否则拖慢采集写入。
OPTIMIZE TABLE和清日志放到凌晨做,别在晚高峰锁表。- 最终目标是让缓存扛住 90% 的请求,MySQL 只处理剩下的 10%。
原文链接:https://www.gj0.com/thread-515.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。