▲ SHOW
执行下面这个命令可以了解服务器的运行状态
mysql >show status;
该命令将显示出一长列状态变量及其对应的值其中包括被中止访问的用户数量被中止的连接数量尝试连接的次数并发连接数量最大值以及其他许多有用的信息这些信息对于确定系统问题和效率低下的原因是十分有用的
SHOW命令除了能够显示出MySQL服务器整体状态信息之外它还能够显示出有关日志文件指定数据库表索引进程和许可权限表的宝贵信息请访问了解更多信息
▲ EXPLAIN
EXPLAIN能够分析SELECT命令的处理过程这不仅对于决定是否要为表加上索引很有用而且对于了解MySQL处理复杂连接的过程也很有用
下面这个例子显示了如何用EXPLAIN提供的信息逐步地优化连接查询(本例来自MySQL文档见原文写到这里似乎有点潦草了事特加上此例)
假定用EXPLAIN分析的SELECT命令如下所示
EXPLAIN SELECT ttTicketNumber ttTimeIn
ttProjectReference ttEstimatedShipDate
ttActualShipDate ttClientID
ttServiceCodes ttRepetitiveID
ttCurrentProcess ttCurrentDPPerson
ttRecordVolume ttDPPrinted etCOUNTRY
et_COUNTRY doCUSTNAME
FROM tt et et AS et_ do
WHERE ttSubmitTime IS NULL
AND ttActualPC = etEMPLOYID
AND ttAssignedPC = et_EMPLOYID
AND ttClientID = doCUSTNMBR;
SELECT命令中出现的表定义如下
※表定义
表 列 列类型
tt ActualPC CHAR()
tt AssignedPC CHAR()
tt ClientID CHAR()
et EMPLOYID CHAR()
do CUSTNMBR CHAR()
※索引
表 索引
tt ActualPC
tt AssignedPC
tt ClientID
et EMPLOYID (主键)
do CUSTNMBR (主键)
※ttActualPC值分布不均匀
在进行任何优化之前EXPLAIN对SELECT执行分析的结果如下
table type possible_keyskey key_len ref rows Extra
etALL PRIMARY NULL NULLNULL
doALL PRIMARY NULL NULLNULL
et_ ALL PRIMARY NULL NULLNULL
ttALL AssignedPCClientIDActualPC NULL NULLNULL
range checked for each record (key map: )
每一个表的type都是ALL它表明MySQL为每一个表进行了完全连接!这个操作是相当耗时的因为待处理行的数量达到每一个表行数的乘积!即这里的总处理行数为 * * * =
这里的问题之一在于如果数据库列的声明不同MySQL(还)不能有效地运用列的索引在这个问题上VARCHAR和CHAR是一样的除非它们声明的长度不同由于ttActualPC声明为CHAR()而etEMPLOYID声明为CHAR()因此这里存在列长度不匹配问题
为了解决这两个列的长度不匹配问题用ALTER TABLE命令把ActualPC列从个字符扩展到字符如下所示
mysql > ALTER TABLE tt MODIFY ActualPC VARCHAR();
现在ttActualPC和etEMPLOYID都是VARCHAR()了执行EXPLAIN进行分析得到的结果如下所示
table typepossible_keyskey key_len ref rowsExtra
ttALLAssignedPCClientIDActualPC NULL NULL NULL where used
doALLPRIMARY NULLNULLNULL
range checked for each record (key map: )
et_ ALLPRIMARY NULLNULLNULL
range checked for each record (key map: )
eteq_ref PRIMARY PRIMARY ttActualPC
这还算不上完美但已经好多了(行数的乘积现在少了一个系数)现在这个SQL命令执行大概需要数秒钟时间
为了避免ttAssignedPC = et_EMPLOYID以及ttClientID = doCUSTNMBR比较中的列长度不匹配我们可以进行如下改动
mysql > ALTER TABLE tt MODIFY AssignedPC VARCHAR()
MODIFY ClientIDVARCHAR();
现在EXPLAIN显示的结果如下
table typepossible_keyskey key_len refrows Extra
etALLPRIMARY NULLNULLNULL
ttrefAssignedPCClientIDActualPC ActualPC etEMPLOYID where used
et_ eq_ref PRIMARY PRIMARY ttAssignedPC
doeq_ref PRIMARY PRIMARY ttClientID
这个结果已经比较令人满意了
余下的问题在于默认情况下MySQL假定ttActualPC列的值均匀分布而事实上tt表的情况并非如此幸而我们可以很容易地让MySQL知道这一点
shell > myisamchk analyze PATH_TO_MYSQL_DATABASE/tt
shell > mysqladmin refresh
现在这个连接操作已经非常理想EXPLAIN分析的结果如下
table typepossible_keyskey key_len refrowsExtra
ttALLAssignedPCClientIDActualPC NULL NULL NULLwhere used
eteq_ref PRIMARY PRIMARY ttActualPC
et_ eq_ref PRIMARY PRIMARY ttAssignedPC
doeq_ref PRIMARY PRIMARY ttClientID
▲ OPTIMIZE
OPTIMIZE能够恢复和整理磁盘空间以及数据碎片一旦对包含变长行的表进行了大量的更新或者删除进行这个操作就非常有必要了OPTIMIZE当前只能用于MyISAM和BDB表
结束语
从编译数据库服务器开始贯穿整个管理过程能够改善MySQL性能的因素实在非常多本文只涉及了其中很小的一部分