性能优化是通过某些有效的方法提高MySQL数据库的性能。性能优化的目的是为了是MySQL数据运行速度更快、占用的磁盘空间更小。性能优化包括很多方面,例如优化查询速度、优化更新速度和优化MySQL服务器等。
MySQL数据库的用户和数据非常少的时候,很难判断一个MySQL数据库的性能的好坏。只有当长时间运行,并且有大量用户进行频繁操作时,MySQL数据库的性能才能体现出来。例如,一个每天有几万用户同时在线的大型网站的数据库性能的优劣就很明显。这么多用户在同时连接MySQL数据库,并且进行查询、插入和更新的操作。如果MySQL数据库的性能很差,很可能无法承受如此多用户同时操作。试想用户查询一条记录需要花费很长时间,用户很难会喜欢这个网站。
因此,为了提高MySQL数据库的性能,需要进行一系列的优化措施。如果MySQL数据库需要进行大量的查询操作,那么就需要对查询语句进行优化。对于耗费时间的查询语句进行优化,可以提高整体的查询速度。如果连接MySQL数据库用户很多,那么就需要对MySQL服务器进行优化。否则,大量的用户同时连接MySQL数据库,可能会造成数据库系统崩溃。
数据库管理员可以使用SHOW STATUS语句查询MySQL数据库的性能,通过这些参数可以分析MySQL数据库性能,然后根据分析结果,进行相应的性能优化。语法形式如下:
SHOW STATUS LIKE 'value';
其中,value参数是常用的几个统计参数。这些常用参数介绍如下。
Connections:连接MySQL服务器的次数;
Uptime:MySQL服务器的上线时间;
Slow_queries:慢查询的次数;
Com_select:查询操作的次数;
Com_insert:插入操作的次数;
Com_delete:删除操作的次数。
ps:MySQL中存在查询InnoDB类型的表的一些参数。例如,Innodb_rows_read参数表示SELECT语句查询的记录数;Innodb_rows_inserted参数表示INSERT语句插入的记录数;Innodb_rows_updated参数表示UPDATE语句更新的记录数;Innodb_rows_deleted参数表示DELETE语句删除的记录数。
优化查询
分析语句查询
在MySQL中,可以使用EXPLAIN语句和DESCRIBE语句来分析查询语句。
应用EXPLAIN关键字分析查询语句,其语法结构如下:
EXPLAIN SELECT语句;
EXPLAIN|DESCRIBE SELECT * FROM timeinfo; 其中,各字段所代表的意义如下所示: id列:指定在整个查询中SELECT的位置。 table列:存放查询的表名。 type列:连接类型,该列中存储很多值,范围从const到ALL。 possible_keys列:指定为了提高查找速度,在MySQL中可以使用的索引。 key列:指定实际使用的键。 rows列:指定MySQL需要在相应表中返回查询结果所检验的行数,为了得到该总行数,MySQL必须扫描处理整个查询,再乘以每个表的行值。 Extra列:包含一些其他信息,设计MySQL如何处理查询。
索引对查询速度的影响
在查询过程中使用索引,势必会提高数据库查询效率,应用索引来查询数据库中的内容,可以减少查询的记录数,从而达到优化查询的目的。
使用索引查询
在MySQL中,索引可以提高查询的速度,但并不能充分发挥其作用,所以在应用索引查询时,也可以通过关键字或其他方式来对查询进行优化处理。
1.应用LIKE关键字优化索引查询
如果匹配字符串中,第一个字符为百分号“%”时,索引不会被使用,如果“%”所在匹配字符串中的位置不是第一位置,则索引会被正常使用。
2.查询语句中使用多列索引
多列索引是指在表的多个字段上创建一个索引,当且仅当只有查询条件中使用了这些字段中的一个字段时,索引才会被正常使用。
应用多列索引在表的多个字段中创建一个索引,其命令如下:
CREATE INDEX index_student_info ON studentinfo(name, sex);
ps:在应用sex字段时,索引不能被正常使用。这就意味着索引并未在MySQL优化中起到任何作用,故必须使用第一字段name时,索引才可以被正常使用。
3.查询语句中使用OR关键字
在MySQL中,查询语句只有包含OR关键字时,要求查询的两个字段必须同为索引,如果所搜索的条件中,有一个字段不为索引,则在查询中不会应用索引进行查询。其中,应用OR关键字查询索引的命令如下: SELECT * FROM studentinfo WHERE name='Chris' or sex='M';
优化数据库结构
数据库结构是否合理,需要考虑是否存在冗余、对表的查询和更新的速度、表中字段的数据类型是否合理等多方面的内容。
将字段很多的表分解成多个表
有些表在设计时设置了很多的字段。这个表中有些字段的使用频率很低。当这个表的数据量很大时,查询数据的速度就会很慢。对于这种字段特别多且有些字段的使用频率很低的表,可以将其分解成多个表。
学生表中有很多字段,其中在extra字段中存储着学生的备注信息。有些备注信息的内容特别多,但是,备注信息很少使用。这样就可以分解出另外一个表。将这个取名为student_extra的表中存储两个字段,分别为id和extra。其中,id字段为学生的学号,extra字段存储备注信息。如果需要查询某个学生的备注信息,可以用学号(id)来查询。如果需要将学生的学籍信息与备注信息同时显示时,可以将student表和student_extra表进行联表查询,查询语句如下:
SELECT*FROM student, student_extra WHERE student.id=student_extra.id;
通过这种分解,可以提高student表的查询效率。因此,遇到这种字段很多,而且有些字段使用不频繁的,可以通过这种分解的方式来优化数据库的性能。
增加中间表
有时需要经常查询某两个表中的几个字段。如果经常进行联表查询,会降低MySQL数据库的查询速度。对于这种情况,可以建立中间表来提高查询速度。
先分析经常需要同时查询哪几个表中的哪些字段,然后将这些字段建立一个中间表,并将原来那几个表的数据插入到中间表中,之后就可以使用中间表来进行查询和统计。
实际中经常要查学生的学号、姓名和成绩。根据这种情况可以创建一个temp_score表。temp_score表中存储3个字段,分别是id、name和grade。CREATE语句执行如下:
CREATE TABLE temp_score(
id INT NOT NULL,
Name VARCHAR(20)NOT NULL,
grade FLOAT);
然后从student表和score表中将记录导入到temp_score表中。INSERT语句如下:
INSERT INTO temp_score SELECT student.id, student.name, score.grade
FROM student, score WHERE student.id=score.stu_id;
将这些数据插入到temp_score表中以后,可以直接从temp_score表中查询学生的学号、姓名和成绩。这样就省去了每次查询时进行表连接,从而提高数据库的查询速度。
优化插入记录的速度
插入记录时,索引、唯一性校验都会影响到插入记录的速度;而且一次插入多条记录和多次插入记录所耗费的时间是不一样的。根据这些情况,分别进行不同的优化。
1.禁用索引
插入记录时,MySQL会根据表的索引对插入的记录进行排序。如果插入大量数据时,这些排序会降低插入记录的速度。为了解决这种情况,在插入记录之前先禁用索引,等到记录都插入完毕后再开启索引。禁用索引的语句如下:
ALTER TABLE 表名 DISABLE KEYS;
重新开启索引的语句如下:
ALTER TABLE 表名 ENABLE KEYS;
对于新创建的表,可以先不创建索引,等到记录都导入以后再创建索引,这样可以提高导入数据的速度。
2.禁用唯一性检查
插入数据时,MySQL会对插入的记录进行校验。这种校验也会降低插入记录的速度,可以在插入记录之前禁用唯一性检查,等到记录插入完毕后再开启。禁用唯一性检查的语句如下:
SET UNIQUE_CHECKS=0;
重新开启唯一性检查的语句如下:
SET UNIQUE_CHECKS=1;
3.优化INSERT语句
插入多条记录时,可以采取两种写INSERT语句的方式。第一种是一个INSERT语句插入多条记录。INSERT语句的情形如下:
INSERT INTO food VALUES
(NULL,'果冻','CC果冻厂',1.8,'2009','北京'),
(NULL,'咖啡','CF咖啡厂',25,'2010','天津'),
(NULL,'奶糖','旺仔奶糖',15,'2011','广东');
第二种是一个INSERT语句只插入一条记录,执行多个INSERT语句来插入多条记录。INSERT语句的情形如下:
INSERT INTO food VALUES(NULL,'果冻','CC果冻厂',1.8,'2009','北京');
INSERT INTO food VALUES(NULL,'咖啡','CF咖啡厂',25,'2010','天津');
INSERT INTO food VALUES(NULL,'奶糖','旺仔奶糖',15,'2011','广东');
第一种方式减少了与数据库之间的连接等操作,其速度比第二种方式要快。
ps:当插入大量数据时,建议使用一个INSERT语句插入多条记录的方式;而且如果能用LOAD DATA INFILE语句,就尽量用LOAD DATA INFILE语句,因为LOAD DATA INFILE语句导入数据的速度比INSERT语句的速度快。
分析表、检查表和优化表
分析表主要作用是分析关键字的分布;检查表主要作用是检查表是否存在错误;优化表主要作用是消除删除或者更新造成的空间浪费。
1.分析表
MySQL中使用ANALYZE TABLE语句来分析表,该语句的基本语法如下:
analyze table 表名1,表名2……;
使用analyze table分析表的过程中,数据库系统会对表加一个只读锁,在分析期间,只能读取表中的记录,不能更新和插入记录。ANALYZE TABLE语句能够分析InnoDB和MyISAM类型的表。
详细介绍如下:
Table:表示表的名称;
Op:表示执行的操作。analyze表示进行分析操作;check表示进行检查查找;optimize表示进行优化操作;
Msg_type:表示信息类型,其显示的值通常是状态、警告、错误和信息这四者之一;
Msg_text:显示信息。
检查表和优化表之后也会出现这4列信息。
2.检查表
MySQL中使用CHECK TABLE语句来检查表。CHECK TABLE语句能够检查InnoDB和MyISAM类型的表是否存在错误;而且,该语句还可以检查视图是否存在错误。该语句的基本语法如下:
check table 表名1,表名2…… [option];
其中,option参数有5个参数,分别是QUICK、FAST、CHANGED、MEDIUM和EXTENDED。这5个参数的执行效率依次降低。option选项只对MyISAM类型的表有效,对InnoDB类型的表无效。CHECK TABLE语句在执行过程中也会给表加上只读锁。
3.优化表
MySQL中使用optimize table语句来优化表。该语句对InnoDB和MyISAM类型的表都有效。但是,optimize table只能优化表中的VARCHAR、BLOB或TEXT类型的字段。optimize table语句的基本语法如下:
optimize table 表名1,表名2……;
通过optimize table语句可以消除删除和更新造成的磁盘碎片,从而减少空间的浪费。OPTIMIZE TABLE语句在执行过程中也会给表加上只读锁。
ps:如果一个表使用了TEXT或者BLOB这样的数据类型,那么更新、删除等操作就会造成磁盘空间的浪费,因为,更新和删除操作后,以前分配的磁盘空间不会自动收回。使用optimize table语句就可以将这些磁盘碎片整理出来,以便以后再利用。
查询高速缓存
在MySQL中,用户通过SELECT语句查询数据时,该操作将结果集保存到一个特殊的高级缓存中,从而实现查询操作。首次查询后,当用户再次做相同查询操作时,MySQL即可从高速缓存中检索结果。这样一来,既提高了查询效率,同样起到优化查询的作用。
检验高速缓存是否开启
SHOW VARIABLES LIKE'%query_cache%';
主要的参数进行说明:
have_query_cache:表明服务器在默认安装条件下,是否已经配置查询高速缓存。
query_cache_size:高速缓存分配空间,如果该空间为86,则证明分配给高速缓存空间的大小为86MB。如果该值为0,则表明查询高速缓存已经关闭。
query_cache_type:判断高速缓存开启状态,其变量值范围为0~2。其中,当该值为0或OFF时,表明查询高速缓存已经关闭;当该值为1或ON时,表明高速缓存已经打开;其值为2或DEMAND时,表明要根据需要运行有SQL_CACHE选项的SELECT语句,提供查询高速缓存。
使用高速缓存
在MySQL中,查询高速缓存的具体语法结构如下:
SELECT SQL_CACHE * FROM 表名;
如果经常运行查询高速缓存,将会提高MySQL数据库的性能。
一旦表有变化,查询这个表的高速缓存将会失效,且将从高速缓存中删除。这样防止查询从旧表中返回无效数据。另外,不使用高速缓存查找可以应用SQL_NO_CACHE关键字。