贴一个从红盟那边copy过来的数据库调优的帖子
早上帮朋友一台服务器解决了 Mysql cpu 占用 100% 的问题。稍整理了一下,将经验记录在这篇文章里。
朋友主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU 占用率总为 100% 高居不下。此主机有10个左右的 database, 分别给十个网站调用。据朋友测试,导致 mysqld-nt.exe cpu 占用奇高的是网站A,一旦在 IIS 中将此网站停止服务,CPU 占用就降下来了。一启用,则马上上升。
MYSQL CPU 占用 100% 的解决过程
今天早上仔细检查了一下。目前此网站的七日平均日 IP 为2000,PageView 为 3万左右。网站A 用的 database 目前有39个表,记录数 60.1万条,占空间 45MB。按这个数据,MySQL 不可能占用这么高的资源。
于是在服务器上运行命令,将 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% 的 优化笔记 [url]http://www.xiaohui.com/dev/server/20070701-discuz-mysql-cpu-100-optimize.htm[/url])
解决 MYSQL CPU 占用 100% 的经验总结
增加 tmp_table_size 值。mysql 的配置文件中,tmp_table_size 的默认大小是 32M。如果一张临时表超出该大小,MySQL产生一个 The table tbl_name is full 形式的错误,如果你做很多高级 GROUP BY 查询,增加 tmp_table_size 值。 这是 mysql 官方关于此选项的解释:
tmp_table_size
This variable determines the maximum size for a temporary table in memory. If the table becomes too large, a MYISAM table is created on disk. Try to avoid temporary tables by optimizing the queries where possible, but where this is not possible, try to ensure temporary tables are always stored in memory. Watching the processlist for queries with temporary tables that take too long to resolve can give you an early warning that tmp_table_size needs to be upped. Be aware that memory is also allocated per-thread. An example where upping this worked for more was a server where I upped this from 32MB (the default) to 64MB with immediate effect. The quicker resolution of queries resulted in less threads being active at any one time, with all-round benefits for the server, and available memory.
对 WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的条件判断中用到的字段,应该根据其建立索引 INDEX。索引被用来快速找出在一个列上用一特定值的行。没有索引,MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行。表越大,花费时间越多。如果表对于查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要考虑所有数据。如果一个表有1000行,这比顺序读取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储。
根据 mysql 的开发文档:
索引 index 用于:
快速找出匹配一个WHERE子句的行
当执行联结(JOIN)时,从其他表检索行。
对特定的索引列找出MAX()或MIN()值
如果排序或分组在一个可用键的最左面前缀上进行(例如,ORDER BY key_part_1,key_part_2),排序或分组一个表。如果所有键值部分跟随DESC,键以倒序被读取。
在一些情况中,一个查询能被优化来检索值,不用咨询数据文件。如果对某些表的所有使用的列是数字型的并且构成某些键的最左面前缀,为了更快,值可以从索引树被检索出来。
假定你发出下列SELECT语句:
mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
如果一个多列索引存在于col1和col2上,适当的行可以直接被取出。如果分开的单行列索引存在于col1和col2上,优化器试图通过决定哪个索引将找到更少的行并来找出更具限制性的索引并且使用该索引取行。
开发人员做 SQL 数据表设计的时候,一定要通盘考虑清楚
分享到:
相关推荐
《mysql管理之道:性能调优、高可用与监控》由资深mysql专家撰写,以最新的mysql版本为基础,以构建高性能mysql服务器为核心,从故障诊断、表设计、sql优化、性能参数调优、mydumper逻辑、xtrabackup热备份与恢复、...
### MySQL索引与SQL调优知识点详解 #### 一、MySQL简介及背景 MySQL是一款广泛使用的开源关系型数据库管理系统(RDBMS),最初由瑞典MySQL AB公司开发。2008年1月,Sun Microsystems将其收购;随后在2009年,Oracle ...
最后,对于每一个调优案例,都应当考虑它特定的应用场景和业务需求。数据库调优是一个持续的过程,需要根据实际情况不断测试、分析和调整。在调优过程中,了解和掌握数据库的内部工作机制,以及熟悉相关调优工具和...
《DB2 SQL性能调优秘笈》不仅详尽阐述了100余条SQL语句优化的技巧和最佳实践、编写高性能SQL语句的标准和原则,以及DB2数据库性能优化的“15步法”,而且还包含大量案例,为解决各种复杂的DB2性能问题提供了解决方案...
通过对一个具体的SQL调优案例进行分析,我们将掌握如何分析执行计划,找出性能瓶颈,并进行有效的优化。 首先,文档中提到了一个具体的SQL查询案例。这个查询的目的是计算在特定登录时间之前的用户数量。SQL语句...
2. 一条 SQL 进入 MySQL Server 到查询结果输出分哪些阶段? 将 MySQL 内部对 SQL 查询的流程进行梳理,采用排除法定位问题。MySQL 主要有三个组件:连接/线程处理、MySQL Server 层、存储引擎层。 MySQL 查询执行...
### MySQL开发核心知识点详解 #### 一、MySQL简介与特点 **MySQL** 是一款流行的开源关系型数据库管理系统(RDBMS),广泛应用于Web应用程序...希望每一位学习MySQL的朋友都能在这条道路上不断前进,实现自己的目标。
从提供的文件内容中,我们可以提炼出以下几个知识点,这些知识点主要涉及SQL语句调优以及MySQL数据库性能优化: 1. 亿级数据量下SQL性能调优的重要性:在处理包含亿级数据量的电商平台商品系统时,SQL性能调优变得...
总的来说,千万级用户场景下的运营系统SQL调优是一项系统性的工程,涉及到数据库设计、SQL编写、索引优化、硬件资源利用等多个层面。通过上述方法,可以有效地提升系统的处理能力和响应速度,为用户提供更流畅的服务...
在本资源中,我们有一个名为"MySQL官网测试数据上百万条数据sql文件"的压缩包,它包含了一个或多个SQL脚本,这些脚本设计用于在MySQL数据库中创建并填充大量的测试数据。 SQL(Structured Query Language)是用于...
每一行代表一条记录,每一列表示一种属性。 - **索引**:用于提高数据检索速度的数据结构,类似于书籍中的目录,能够快速定位到所需数据的位置。 - **存储引擎**:MySQL 支持多种存储引擎,如 InnoDB、MyISAM 等,...
在这个名为"115 案例实战:数十亿数量级评论系统的SQL调优实战(1)"的PDF中,讨论的是一个针对大规模商品评论系统的SQL优化问题。这个系统处理的数据量极其庞大,达到十亿级别的评论数据,因此采用了分库分表策略,...
《MySQL Cookbook》是一本专为面临MySQL问题的各层次用户设计的实用指南,它提供了大量高效、简洁的代码片段和实战案例,旨在帮助读者迅速找到解决方案,而不必从头研究MySQL的基础理论。这本书覆盖了数据库管理、...
MySQL是世界上最受欢迎的关系型数据库管理系统之一,尤其在Web开发、企业级应用、数据分析和云计算等领域广泛应用。面试中,了解MySQL的基础知识和高级特性是至关重要的。以下是一些可能的面试问题及其答案,涵盖了...
本文将探讨一个具体的案例,即一条慢SQL查询如何导致整个网站宕机,并提供相应的解决方法。 首先,让我们分析问题的核心:一条SQL查询耗时70秒。在大多数情况下,查询时间较长可能由于未充分利用索引或者查询逻辑...
【MyCat性能测试案例2】涉及的是对分布式数据库中间件MyCat进行的一次性能测试,主要目的是评估其在特定环境下的处理能力。这次测试选用的MyCat版本是1.2 (SVN 445),这是一个相对稳定的版本。操作系统是Windows 7 ...