当前位置:首页 > Mysql教程 > 列表

mysql服务器常见的优化方法

发布:smiling 来源: PHP粉丝网  添加日期:2014-09-24 13:46:00 浏览: 评论:0 

1.查询时,能不用* 就不用,尽量写全字段名。

2.索引不是越多越好,每个表控制在6个索引以内。范围where条件的情况下,索引不起作用,比如where value<100

3.大部分情况连接效率远大于子查询,但是有例外。当你对连接查询的效率都感到不能接受的时候可以试试用子查询,虽然大部分情况下你会更失望,但总有碰到惊喜的时候不是么…

4.多用explain 和 profile分析查询语句

5.有时候可以1条大的SQL可以分成几个小SQL顺序执行,分了吧,速度会快很多。

6.每隔一段时间用alter table table_name engine=innodb;优化表

7.连接时注意:小表 jion 大表的原则

8.学会用explain 和 profile判断是什么原因使你的SQL慢。

9.查看慢查询日志,找出执行时间长的SQL试着优化去吧~~

优化Group By语句

默认情况下,MySQL 排序所有GROUP BY col1,col2,....。查询的方法如同在查询中指定ORDER BY col1,col2,...。如果显式包括一个包含相同的列的ORDER BY子句,MySQL 可以毫不减速地对它进行优化,尽管仍然进行排序。如果查询包括GROUP BY 但你想要避免排序结果的消耗,你可以指定ORDER BY NULL禁止排序。

优化Order by语句

在某些情况中,MySQL 可以使用一个索引来满足ORDER BY 子句,而不需要额外的排序。where 条件和order by 使用相同的索引,并且order by 的顺序和索引顺序相同,并且order by 的字段都是升序或者都是降序。

优化insert语句

如果你同时从同一客户插入很多行,使用多个值表的INSERT 语句。这比使用分开 INSERT 语句快(在一些情况中几倍),代码如下:

Insert into test values(1,2),(1,3),(1,4)… 

如果你从不同客户插入很多行,能通过使用INSERT DELAYED 语句得到更高的速度。Delayed 的含义是让insert 语句马上执行,其实数据都被放在内存的队列中,并没有真正的写入磁盘;这比每条语句都分别插入要快的多;LOW_PRIORITY刚好相反,在所有其他用户对表的读写完成后才进行插入。

将索引文件和数据文件分在不同的磁盘上存放(利用建表中的选项);

如果进行批量插入,可以增加bulk_insert_buffer_size 变量值的方法来提高速度,但是,这只能对myisam表使用

当从一个文本文件装载一个表时,使用LOAD DATA INFILE。这通常比使用很多INSERT语句快20倍;

根据应用情况使用replace 语句代替insert;

根据应用情况使用ignore 关键字忽略重复记录。

大批量插入数据

1. 对于Myisam 类型的表,可以通过以下方式快速的导入大量的数据,代码如下:

  1. ALTER TABLE tblname DISABLE KEYS; 
  2. loading the data 
  3. ALTER TABLE tblname ENABLE KEYS;  

这两个命令用来打开或者关闭Myisam 表非唯一索引的更新。在导入大量的数据到一个非空的Myisam 表时,通过设置这两个命令,可以提高导入的效率。对于导入大量数据到一个空的Myisam 表,默认就是先导入数据然后才创建索引的,所以不用进行设置。

2. 而对于Innodb 类型的表,这种方式并不能提高导入数据的效率。对于Innodb 类型的表,我们有以下几种方式可以提高导入的效率:

a. 因为Innodb 类型的表是按照主键的顺序保存的,所以将导入的数据按照主键的顺序排列,可以有效的提高导入数据的效率。如果Innodb 表没有主键,那么系统会默认创建一个内部列作为主键,所以如果可以给表创建一个主键,将可以利用这个优势提高导入数据的效率。

b. 在导入数据前执行SET UNIQUE_CHECKS=0,关闭唯一性校验,在导入结束后执行SETUNIQUE_CHECKS=1,恢复唯一性校验,可以提高导入的效率。

c. 如果应用使用自动提交的方式,建议在导入前执行SET AUTOCOMMIT=0,关闭自动提交,导入结束后再执行SET AUTOCOMMIT=1,打开自动提交,也可以提高导入的效率。

查询的优化

读为主可以设置low_priority_updates=1,写的优先级调低,告诉MYSQL尽量先处理读求.

为查询缓存优化你的查询

大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了。

这里最主要的问题是,对于程序员来说,这个事情是很容易被忽略的。因为,我们某些查询语句会让MySQL不使用缓存。请看下面的示例:

  1. // 查询缓存不开启  
  2. $r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()");  
  3.  
  4. // 开启查询缓存  
  5. $today = date("Y-m-d");  
  6. $r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");  

拆分大的 DELETE 或 INSERT 语句

如果你需要在一个在线的网站上去执行一个大的 DELETE 或 INSERT 查询,你需要非常小心,要避免你的操作让你的整个网站停止相应。因为这两个操作是会锁表的,表一锁住了,别的操作都进不来了。

Apache 会有很多的子进程或线程。所以,其工作起来相当有效率,而我们的服务器也不希望有太多的子进程,线程和数据库链接,这是极大的占服务器资源的事情,尤其是内存。

如果你把你的表锁上一段时间,比如30秒钟,那么对于一个有很高访问量的站点来说,这30秒所积累的访问进程/线程,数据库链接,打开的文件数,可能不仅仅会让你泊WEB服务Crash,还可能会让你的整台服务器马上?炝恕?/p>

所以,如果你有一个大的处理,你定你一定把其拆分,使用 LIMIT 条件是一个好的方法,下面是一个示例:

  1. while (1) {  
  2.     //每次只做1000条  
  3.     mysql_query("DELETE FROM logs WHERE log_date <= '2009-11-01' LIMIT 1000");  
  4.     if (mysql_affected_rows() == 0) {  
  5.         // 没得可删了,退出phpfensi.com!  
  6.         break;  
  7.     }  
  8.     // 每次都要休息一会儿  
  9.     usleep(50000);  

where语句的优化

1.尽量避免在 where 子句中对字段进行表达式操作,代码如下:

select id from uinfo_jifen where jifen/60 > 10000;

优化后:

Select id from uinfo_jifen where jifen>600000; 

2.应尽量避免在where子句中对字段进行函数操作,这将导致mysql放弃使用索引,代码如下:

select uid from imid where datediff(create_time,'2011-11-22')=0

优化后:select uid from imid where create_time> ='2011-11-21‘ and create_time<‘2011-11-23’;

索引的优化

MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE.

尽量不要写!=或者<>的sql,用between或> and <代替,否则可能用不到索引,Order by 、Group by 、Distinct 最好在需要这个列上建立索引,利于索引排序.

尽量利用mysql索引排序,没办法的情况下,使用强制索引Force index(index_name),尽量避勉innodb用非常大尺寸的字段作为主键,较频繁的作为查询条件的字段应该创建索引;,选择性高的字段比较适合创建索引;,作为表关联字段一般都需要创索引,更新非常频繁的字段不适合创建索引;,不会出现在 WHERE 子句中的字段不该创建索引.选择性太低的字段不适合单独创建索引,尽量不要用子查询,代码如下:

  1. mysql> explain select uid_,count(*) from smember_6 where uid_ in (select uid_ from alluid) group by uid_; 
  2. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
  3. +----+--------------------+-----------+-------+---------------+---------+---------+------+----------+--------------------------+ 
  4. | 1 | PRIMARY | smember_6 | index | NULL | PRIMARY | 8 | NULL | 53431264 | Using where; Using index |  
  5. | 2 | DEPENDENT SUBQUERY | alluid | ALL | NULL | NULL | NULL | NULL | 2448 | Using where | 
  6.  
  7. --优化后 
  8.  
  9. | mysql> explain select a.uid_,count(*) from smember_6 a,alluid b where a.uid_=b.uid_ group by uid_; 
  10. +----+-------------+-------+------+---------------+---------+---------+------------+------+---------------------------------+ 
  11. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
  12. +----+-------------+-------+------+---------------+---------+---------+------------+------+---------------------------------+ 
  13. | 1 | SIMPLE | b | ALL | NULL | NULL | NULL | NULL | 2671 | Using temporary; Using filesort |  
  14. | 1 | SIMPLE | a | ref | PRIMARY | PRIMARY | 4 | ssc.b.uid_ | 1 | Using index 

Join的优化

如果你的应用程序有很多 JOIN 查询,你应该确认两个表中Join的字段是被建过索引的。这样,MySQL内部会启动为你优化Join的SQL语句的机制。

而且,这些被用来Join的字段,应该是相同的类型的。例如:如果你要把 DECIMAL 字段和一个 INT 字段Join在一起,MySQL就无法使用它们的索引。对于那些STRING类型,还需要有相同的字符集才行。(两个表的字符集有可能不一样)

表的优化

尽可能的使用 NOT NULL,除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。

不要以为 NULL 不需要空间,其需要额外的空间,并且,在你进行比较的时候,你的程序会更复杂。 

当然,这里并不是说你就不能使用NULL了,现实情况是很复杂的,依然会有些情况下,你需要使用NULL值。

下面摘自MySQL自己的文档:

“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”

explain 分析

select ….

变体:

1.explain extended select ….

将执行计划“反编译”成select语句;运行show warnings 可以得到被mysql优化器优化后的语句.

2.explain partitions select …

用于分区表的explain,运行结果含义:

type:all,index,range,ref,eq_ref,const,system null 从左到右,最差到最好;

all:full table scan ;mysql将遍历全表以找到匹配的行;

index:index scan; index 和 all的区别在于index类型只遍历索引;

range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值的行,常见与between ,< ,>等查询;

ref:非唯一性索引扫描,返回匹配某个单独值的所有行,常见于使用非唯一索引即唯一索引的非唯一前缀进行查找;

eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常用于主键或者唯一索引扫描;

const,system:当mysql对某查询某部分进行优化,并转为一个常量时,使用这些访问类型,如果将主键置于where列表中,mysql就能将该查询转化为一个常量。

possible keys:

指出mysql能使用哪个索引在表中找到行,查询涉及到的字段若存在索引,则该索引被列出,但是不一定被查询使用。

key:显示mysql在查询中实际使用的索引,若没有使用索引,则显示为null。

key_len:表示索引中使用的字节数,可以通过该列计算查询中使用的索引的长度。key_len显示的值为索引字段的最大长度,并非实际使用长度。即key_len是根据表定义计算而得,不是通过表内检索出的。

ref:表示上述表的连接匹配条件,即哪些列或者常量被用于查找索引上的值;

rows:表示mysql根据表统计信息以及索引选用情况,估算的找到所需记录所需要的行数;

extra:包含不适合在其他列中显示但是十分重要的额外信息

a:using index:该值表示相迎的select操作中使用了覆盖索引(cover index)

b:using where:表示mysql服务器再存储引擎受到记录后进行“后过滤”;

c:using temporary :表示mysql需要使用临时表来存储结果集,常见于排序和分组查询;

d:using filesort:mysql中无法利用索引完成排序,称为“文件排序”;

explain局限:explain不会告诉你关于触发器,存储过程的信息或者用户自定义的函数对查询的影响情况,explain不会考虑cache.

Tags: mysql优化方法 服务器优化

分享到: