于是在服务器上运行命令,将 mysql 当前的环境变量输出到文件 output.txt:
d:\web\mysql mysqld.exe --help output.txt
发现 tmp_table_size 的值是默认的 32M,于是修改 My.ini, 将 tmp_table_size 赋值到 200M:
d:\web\mysql notepad c:\windows\my.ini
[mysqld]
tmp_table_size=200M
然后重启 MySQL 服务 。CPU 占用有轻微下降,以前的CPU 占用波形图是 100% 一根直线,现在则在 97%~100%之间起伏 。这表明调整 tmp_table_size 参数对 MYSQL 性能提升有改善作用 。但问题还没有完全解决 。
于是进入 mysql 的 shell 命令行,调用 show processlist, 查看当前 mysql 使用频繁的 sql 语句:
mysql show processlist;
反复调用此命令,发现网站 A 的两个 SQL 语句经常在 process list 中出现,其语法如下:
SELECT t1.pid, t2.userid, t3.count, t1.date
FROM _mydata AS t1
LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid
LEFT JOIN _mydata_body AS t2 ON t1.pid=t3.pid
ORDER BY t1.pid
LIMIT 0,15
调用 show columns 检查这三个表的结构 :
mysql show columns from _myuser;
mysql show columns from _mydata;
mysql show columns from _mydata_body;
终于发现了问题所在:_mydata 表,只根据 pid 建立了一个 primary key,但并没有为 userid 建立索引 。而在这个 SQL 语句的第一个 LEFT JOIN ON 子句中:
LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid
_mydata 的 userid 被参与了条件比较运算 。于是我为给 _mydata 表根据字段 userid 建立了一个索引:
mysql ALTER TABLE `_mydata` ADD INDEX ( `userid` )
建立此索引之后,CPU 马上降到了 80% 左右 。看到找到了问题所在 , 于是检查另一个反复出现在 show processlist 中的 sql 语句:
SELECT COUNT(*)
FROM _mydata AS t1, _mydata_key AS t2
WHERE t1.pid=t2.pid and t2.keywords = '孔雀'
经检查 _mydata_key 表的结构,发现它只为 pid 建了了 primary key, 没有为 keywords 建立 index 。_mydata_key 目前有 33 万条记录,在没有索引的情况下对33万条记录进行文本检索匹配,不耗费大量的 cpu 时间才怪 。看来就是针对这个表的检索出问题了 。于是同样为 _mydata_key 表根据字段 keywords 加上索引:
mysql ALTER TABLE `_mydata_key` ADD INDEX ( `keywords` )
建立此索引之后 , CPU立刻降了下来,在 50%~70%之间震荡 。
再次调用 show prosslist,网站A 的sql 调用就很少出现在结果列表中了 。但发现此主机运行了几个 Discuz 的论坛程序, Discuz 论坛的好几个表也存在着这个问题 。于是顺手一并解决 , cpu占用再次降下来了 。(2007.07.09 附注:关于 discuz 论坛的具体优化过程,我后来另写了一篇文章,详见:千万级记录的 Discuz! 论坛导致 MySQL CPU 100% 的 优化笔记 )
解决 MYSQL CPU 占用 100% 的经验总结
增加 tmp_table_size 值 。mysql 的配置文件中,tmp_table_size 的默认大小是 32M 。如果一张临时表超出该大小,MySQL产生一个 The table tbl_name is full 形式的错误,如果你做很多高级 GROUP BY 查询 , 增加 tmp_table_size 值 。
对 WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的条件判断中用到的字段,应该根据其建立索引 INDEX 。索引被用来快速找出在一个列上用一特定值的行 。没有索引,MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行 。表越大,花费时间越多 。如果表对于查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要考虑所有数据 。如果一个表有1000行,这比顺序读取至少快100倍 。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储 。
根据 mysql 的开发文档:
索引 index 用于:
快速找出匹配一个WHERE子句的行
推荐阅读
- u盘恢复微信图片过期怎么恢复,怎么从u盘恢复微信聊天记录
- Go语言的GC稳定吗,go语言chan
- linux的命令cd linux的命令窗口怎么进入
- 上海品牌营销策划价位如何,上海一界品牌营销策划有限公司
- 包含vb.net调试教程的词条
- mysqlSQL语句关键字转意,mysql 关键字做字段名
- 大礼包折扣卡代理平台,大礼包礼品卡
- net开发应用程序框架,net框架支持的开发语言包括
- Linux里head命令 linux headers