MySQL性能优化 .

  1. 性能优化  
  2.     性能优化是通过某些有效的方法提高MySQL数据库的性能。性能优化的目的是为了使MySQL数据库运行速度更快、占用的磁盘空间更小。性能优化包括很多方面,例如优化查询速度、优化更新速度、优化MySQL服务器等。  
  3.         - 性能优化的介绍  
  4.         - 优化查询  
  5.         - 优化数据库结构  
  6.         - 优化MySQL服务器  
  7.     18.1 优化简介  
  8.         优化MySQL数据库是数据库管理员的必备技能。通过不同的优化方式达到提高MySQL数据库性能的目的。  
  9.   
  10.         MySQL数据库的用户和数据非常少的时候,很难判断一个MySQL数据库的性能的好坏。只有当长时间运行,并且有大量用户进行频繁操作时,MySQL数据库的性能就会体现出来了。例如,一个每天有几百万用户同时在线的大型网站的数据库性能的优劣就很明显。这么多用户在线的连接MySQL数据库,并且进行查询、插入、更新的操作。如果MySQL数据库的性能很差,很可能无法承受如此多用户同时操作。试想用户查询一条记录需要花费很长时间,用户很难会喜欢这个网站。  
  11.           
  12.         SHOW STATUS LIKE 'value';  
  13.         show status like 'connections';  
  14.         show status like 'Com_select';  
  15.     18.2 优化查询  
  16.         18.2.1 分析查询语句  
  17.             通过对查询语句的分析,可以了解查询语句的执行情况。MySQL中,可以使用explain语句和describe语句来分析查询语句。  
  18.                   
  19.                 explain select语句;  
  20.                 通过explain关键字可以分析后面的select语句的执行情况。并且能够分析出所查询的表的一些内容。  
  21.               
  22.             explain select * from mysql.user;  
  23.             describe select * from mysql.user;  
  24.   
  25.   
  26.             id: # select语句的编号  
  27.             select_type:    # select语句类型 simple(不包括连接查询和子查询)  
  28.             table: student # 表  
  29.             type: # 连接的类型  
  30.             possible_keys:  
  31.             key:  
  32.             key_len:  
  33.             ref:  
  34.             rows:  
  35.             Extra:  
  36.         18.2.2 索引对查询速度的影响  
  37.             索引可以快速的定位表中的某条记录。使用索引可以提高数据库查询的速度,从而提高数据库的性能。  
  38.               
  39.             如果查询时不使用索引,查询语句将查询表中的所有字段。这样查询的速度会很慢。如果使用索引进行查询,查询语句只查询索引字段。这样可以减少查询的记录数,达到提高查询速度的目的。         
  40.             explain select * from student where name="张三" \G  
  41.             create index idx_name on student(name);  
  42.             explain select * from student where name="张三" \G  
  43.               
  44.         18.2.3 使用索引查询  
  45.             索引可以提高查询的速度。但是有些时间即使查询时使用的是索引,但索引并没有起作用。  
  46.   
  47.             1. 查询语句中使用LIKE关键字  
  48.                 explain select * from student where name like '%四' \G  
  49.                 explain select * from student where name like '李%' \G  
  50.                 使用like关键字的时候索引字段的搜索必须开头必须有值开始  
  51.             2. 查询语句中使用多列索引  
  52.                 使用第一个索引字段的时候才会起作用  
  53.                 create index idx_birth_depart on student(birth,department);  
  54.                 explain select * from student where birth > 1990;  
  55.                 explain select * from student where department like '中文%';    
  56.                   
  57.             3. 查询语句中使用OR关键字  
  58.                 两个字段都有索引的时候索引查询,其中一个字段没有索引时不会使用索引查询。      
  59.                 explain select * from student where name="张三" or gender="女" \G  
  60.                 explain select * from student where name="张三" or id=905 \G  
  61.         18.2.4 优化子查询  
  62.             很多查询中需要使用子查询。子查询可以使查询语句很灵活,但子查询的执行效率不高。子查询时,MySQL需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句再临时表中查询记录。查询完毕后,MySQL需要撤销这些临时表。因此,子查询的速度会受到一定的影响。如果查询的数据量比较大,这种影响就会随之增大。在MySQL中可以使用连接查询来替代子查询。连接查询不需要建立临时表,其速度比子查询要快。  
  63.     18.3 优化数据库结构  
  64.         数据库结构是否合理,需要考虑是否存在冗余、对表的查询和更新的速度、表中字段的数据类型否合理等多方面的内容。  
  65.         18.3.1 将字段很多的表分解成多个表  
  66.             有些表在设置时设置了很多的字段。这个表中有些字段的使用频率很低。当这个表的数据量很大时,查询数据的速度就会很慢。  
  67.             对于这种字段特别多且有些字段的使用频率很低的表,可以将其分解成多个表。  
  68.             create table student_extra(  
  69.                 id int primary key,  
  70.                 extra varchar(255)  
  71.             );        
  72.             select * from student,student_extra where studnet.id=student_extra.id;  
  73.         18.3.2 增加中间表  
  74.             有时候需要经常查询某两个表中的几个字段。如果经常进行联表查询,会降低MySQL数据库的查询速度。对于这种情况,可以建立中间表来提高查询速度。  
  75.             先分析经常需要同时查询哪几个表中的哪些字段。然后将这些字段建立一个中间表,并从原来那几个表将数据插入到中间表中。之后就可以使用中间表来进行查询和统计了。  
  76.             desc student;  
  77.             desc score;  
  78.   
  79.             create table temp_score(  
  80.                 id int not null,  
  81.                 name varchar(20) not null,  
  82.                 grade float  
  83.             ) default charset=utf8;  
  84.             insert into temp_score select student.id,student.name,score.grade from student,score where student.id=score.stu_id;  
  85.         18.3.3 增加冗余字段  
  86.             设计数据库表的时候尽量让表达到三范式。但是,有时候为了提高查询速度,可以有意识的在表中增加冗余字段。  
  87.   
  88.             表的规范化程序越高,表与表之间的关系就越多。查询时可能经常需要多个表之间进行连接查询。而进行连接操作会降低查询速度。例如,学生的信息存储在student表中,院系信息存储在department表中,通过student表中的dept_id字段与department表建立关联关系。如果要查询一个学生所在系的名称,必须从student表中查找学生所在院系的编号(dept_id),然后根据这个编号去department查找系的名称。如果经常需要进行这个操作时,连接查询会浪费很多的时候。因此可以在student表中增加一个冗余字段dept_name,该字段用来存储学生所在院系的名称。这样就不用每次都进行连接操作了。  
  89.         18.3.4  优化插入记录的速度  
  90.             插入记录时,索引、惟一性校验都会影响到插入记录的速度。而且,一次插入多条记录和多次插入记录所耗费的时间是不一样的。根据这些情况,分别进行不同的优化。  
  91.   
  92.             1. 禁用索引  
  93.                 插入记录的时候,MySQL会根据对表的索引插入的数据进行排序。如果插入大量数据的时候,这些排序会会降低插入数据的速度。为这解决这个问题,首先插入数据之前先关闭当前表的索引,等数据插入完毕之后再开启索引。  
  94.                   
  95.                 ALTER TABLE 表名 disable keys;    # 禁用当前表的索引  
  96.                 ALTER TABLE 表名 enable keys; # 开启当前表的索引  
  97.             2. 禁用惟一性检查  
  98.                 插入数据的时候,会检测数据的唯一性校验这会降低大量数据的插入速度。  
  99.                   
  100.                 #禁用惟一性检查  
  101.                 set unique_checks=0;  
  102.   
  103.                 # 开启惟一性检查  
  104.                 set unique_checks=1;                  
  105.             3. 优化insert语句  
  106.                 1.一次性插入多条语句(减少数据库连接,速度更优)  
  107.                 2.多次插入语句(相对慢)  
  108.     18.4 分析表、检查表和优化表  
  109.         分析表主要作用是分析关键字的分布。  
  110.         检查表主要作用是检查表是否存在错误。  
  111.         优化表主要作用是消除删除或者更新造成空间浪费。  
  112.   
  113.         18.4.1 分析表  
  114.             使用analyze语句的时候对当前表进行只读锁,在分析表的时候只能读取数的数据,不能更新他插入记录。能够分析InnoDb和MyISAM类型的表。  
  115.             ANALYZE TABLE 表名1[,表名2...];  
  116.             analyze table score;  
  117.             Table       Op  Msg_type    Msg_text  
  118.             test.score  analyze status      OK  
  119.   
  120.             Op:   
  121.             analyze  
  122.             check  
  123.             optimize  
  124.   
  125.             Msg_type:  
  126.             status(状态)   
  127.             warnings(警告)  
  128.             error(错误)  
  129.         18.4.2 检查表(包括视图表)  
  130.             CHECK TABLE 表名1[,表名2...][options]  
  131.             options:只适用于MyISAM类型,且只读锁  
  132.             CHECK TABLE score;  
  133.         18.4.3 优化表  
  134.             适用于引擎类型:InnoDB和MyISAM  
  135.             适用于数据类型:varchar、blob和text类型的字段  
  136.             只读锁  
  137.             OPTIMIZE table 表名1[,表名2...]  
  138.             optimize table score;  
  139.     18.5 优化MySQL服务器  
  140.         优化MySQL服务器可以从两个方面来理解。一个是从硬件方面来进行优化。另一个是从MySQL服务的参数进行优化。通过这些优化方式,可以提供MySQL的运行速度。但是这部分的内容很难理解,一般只有专业的数据库管理员才能进行这一类的优化。  
  141.           
  142.         18.5.1 优化服务器硬件  
  143.             服务器的硬件性能直接决定着MySQL数据库的性能。例如,增加内存和提高硬盘的读写速度,这能够提高MySQL数据库的查询、更新的速度。  
  144.             随着硬件技术的成熟、硬件的价格也随之降低。现在普通的个人电话都已配置了2G内存,甚至一些个人电脑配置4G内存。因为内存的读写速度比硬盘的读写速度快。可以在内存中为MySQL设置更多的缓冲区,这样可以提高MySQL访问的速度。如果将查询频率很高的记录存储在内存中,那查询速度就会很快。  
  145.             如果条件允许,可以将内存提高到4G。并且选择my-innodb-heavy-4G.ini作为MySQL数据库的配置文件。但是,这个配置文件主要支持InnoDB存储引擎的表。如果使用2G内存,可以选择my-huge-ini作为配置文件。而且,MySQL所在的计算机最好是专用数据库服务器。这样数据库可以完全利用该机器的资源。  
  146.         18.5.2 优化MySQL的参数  
  147.             内存中会为MySQL保留部分的缓存区。这些缓存区可以提高MySQL数据库的处理速度。缓存区的大小都是在MySQL的配置文件中进行设置的。  
  148.             MySQL中比较重要的配置参数都在my.cnf或者my.ini文件[mysqld]组中。  
  149.   
  150.             innodb_buffer_pool_size=36M  
  151.     18.6 本章实例   
  152.         (1)查看InnoDB表的查询的记录数和更新的记录数。  
  153.             show status like 'Innodb_rows_read' \G    
  154.             show status like 'Innodb_rows_updated' \G  
  155.         (2)分析查询语句的性能,select语句如下:  
  156.             explain select * from score where stu_id=902 \G  
  157.             analyze table score;  
  158.     18.7 上机实践  
  159.         (1)查看MySQL服务器的连接数、查询次数和慢查询的次数  
  160.             show status like 'Connections';  
  161.             show status like 'Com_select';  
  162.             show status like 'Slow_queries';  
  163.         (2)检查score表  
  164.             check table score;  
  165.         (3)优化score表  
  166.             optimize table socre;  
  167.     18.9 常见问题及解答  
  168.         1. 如何使用查询缓存区?  
  169.             查询缓存区提高查询的速度,这种方式只适用于修改操作少且经常执行相同的查询操作的情况。默认情况下,查询缓存区是禁止的,因为query_cache_size的默认值为0。query_cache_size可以设置有效的使用空间。query_cache_type可以设置查询缓冲区的开启状态,其取值为0、1或者2。在my.cnf或者my.ini中加入下面的语句:  
  170.                 # my.cnf(Linux)或者my.ini(Windows)  
  171.                 [mysqld]  
  172.                 query_cache_size=20M  
  173.                 query_cache_type=1  
  174.   
  175.             query_cache_type取值为1时表示开启查询缓存区。在查询语句中加上SQL_NO_CACHE关键字,该查询语句将不使用查询缓存区。可以使用FLUSH QUERY CACHE语句来清理查询缓存区中的碎片。  
  176.         2. 为什么查询语句中的索引没有发挥作用?  
  177.             在很多情况下,虽然查询语句中使用了索引,但是索引并没有发挥作用。例如,在WHERE条件的LIKE关键字匹配的字符串以"%"开头,这种情况下索引不会起作用。WHERE条件中使用OR关键字来连接多个查询条件,如果有一个条件没有使用索引,那么其它的索引也不会起作用。如果使用多列索引时,多列索引第一个字段没有使用,那么这个多列索引也不起作用。根据这些情况,必须对这些语句进行相应的优化。