mysql的性能优化总结

经验是从别人那里拿来的,不想直接复制黏贴,想亲自总结下,巴拉巴拉.........进入正题吧

一、为查询加入缓存

1、检查数据库是否开启缓存:show variables like '%query_cache%'; 若开启query_cache_type 为 ON

2、设置查询缓存的方法:网上搜素下:http://www.111cn.net/database/mysql/63815.htm(参考链接)

使用缓存和不适用缓存的区别


$r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()");未开启缓存
 
// 开启查询缓存
$today = date("Y-m-d");
$r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");;
两者唯一区别就是CURDATE(),查询缓存对这个函数不起作用,项now()和rand()或者其他sql函数均不会开启查询缓存,所以必须新增一个变量来代替mysql的函数,从而开启缓存

二、EXPLAIN 你的 SELECT 查询

查看rows列可以让我们找到潜在的性能问题。

三、当只要一条数据时,使用limit1,性能会大大提升

这样mysql会在找到一条数据后停止搜索,而不是继续往后查下一条符合记录的数据

下面的示例,只是为了找一下是否有“中国”的用户,很明显,后面的会比前面的更有效率。(请注意,第一条中是Select *,第二条是Select 1)

$r = mysql_query("SELECT * FROM user WHERE country = 'China'");
if (mysql_num_rows($r) > 0) {
    // ...
}
 
// 有效率的:
$r = mysql_query("SELECT 1 FROM user WHERE country = 'China' LIMIT 1");
if (mysql_num_rows($r) > 0) {
    // ...
}

四、为搜索字段加上索引

索引并不一定只是给主键和唯一的字段,加上索引,而是如果有某个字段经常会用到,则为其加上索引

如果某个字段查询时如 like“a%”,则可以用上索引,但是如果想like“%a%”则索引没意义

五、在使用join时,两个表的字段类型要一致,,而且是被索引过的,myql内部会启为你优化join的字段

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

$r = mysql_query("SELECT company_name FROM users
    LEFT JOIN companies ON (users.state = companies.state)
    WHERE users.id = $user_id");
 
// 两个 state 字段应该是被建过索引的,而且应该是相当的类型,相同的字符集。

六、不要用select * 应该使用什么字段就去取什么字段,因为从数据库读越多的数据查询就越慢,而且如果时web服务器和数据库服务器时两台独立的服务器还会增加网络传输的负载

七、永远为每张表设置一个主键id

类型最好时int型的,varchar会使得性能下降, 推荐使用UNSIGNED),并设置上自动增加的AUTO_INCREMENT标志。 在这里,只有一个情况是例外,那就是“关联表”的“外键”,也就是说,这个表的主键,通过若干个别的表的主键构成。我们把这个情况叫做“外键”。比如:有一个“学生表”有学生的ID,有一个“课程表”有课程ID,那么,“成绩表”就是“关联表”了,其关联了学生表和课程表,在成绩表中,学生ID和课程ID叫“外键”其共同组成主键。

八、使用enum而不是varchar,

ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。

如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。

MySQL也有一个“建议”(见第十条)告诉你怎么去重新组织你的表结构。当你有一个 VARCHAR 字段时,这个建议会告诉你把其改成 ENUM 类型。使用 PROCEDURE ANALYSE() 你可以得到相关的建议。

 

九、尽可能使用not null

空值('')是不占用空间的
NULL值是未知的,且占用空间,不走索引,DBA建议建表的时候最好设置字段是NOT NULL 来避免这种低效率的事情的发生。
注意:
count()统计某列的记录数的时候,如果采用的NULL值,会别系统自动忽略掉,但是空值是会进行统计到其中的。
对于timestamp数据类型,如果往这个数据类型插入的列插入NULL值,则出现的值是当前系统时间。插入空值,则会出现 '0000-00-00 00:00:00'

 十、IP地址 地址存成 UNSIGNED INT

十一、固定长度的表会更快

如果表中所有的字段都时固定长度,则整个表会被认为是static或者fixed-length 例如,表中没有如下类型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一个这些字段,那么这个表就不是“固定长度静态表”了

十二、垂直分割

就是一个大表切割成多个小表,可以降低表的复杂度和字段的数目,从而达到优化

实例1:在user表中有一个字段是家庭地址等啊,在这个表中除了个人信息除外,并不常读取和改写这个字段,何不吧他放倒另外一张表中,这样会提高 表的性能

实例2:这个表中有一个是last——login的字段,每次登录完毕都会更新,但是每次更新时都会吧表的查询缓存清空,所以可以吧这个字段放倒另外一个表中,这样就不会影响你对username等字段的频繁查询,因为查询缓存会提高性能。查询缓存保留了返回客户端数据的完整结果,当缓存被命中时,服务器会马上返回保存的结果,并且跳过解析,优化和执行的步骤,缓存也需要开销,只有在节省的资源大于开销的时候,缓存才会真正的油效率,这和服务器的负载有关

十三、拆分大的delete和insert语句

因为会锁表,会造成web crash

十四、越小的列越快

如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。

十五、选择正确的搜索引擎:

在 MySQL 中有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。酷壳以前文章《MySQL: InnoDB 还是 MyISAM?》讨论和这个事情。

MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。

InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。

16. 小心“永久链接”

“永久链接”的目的是用来减少重新创建MySQL链接的次数。当一个链接被创建了,它会永远处在连接的状态,就算是数据库操作已经结束了。而且,自从我们的Apache开始重用它的子进程后——也就是说,下一次的HTTP请求会重用Apache的子进程,并重用相同的 MySQL 链接。

在理论上来说,这听起来非常的不错。但是从个人经验(也是大多数人的)上来说,这个功能制造出来的麻烦事更多。因为,你只有有限的链接数,内存问题,文件句柄数,等等。

而且,Apache 运行在极端并行的环境中,会创建很多很多的了进程。这就是为什么这种“永久链接”的机制工作地不好的原因。在你决定要使用“永久链接”之前,你需要好好地考虑一下你的整个系统的架构。

 

posted @ 2016-01-19 21:27  YaChenYa  阅读(249)  评论(0编辑  收藏  举报