您的位置:首页 > 数据库 > MySQL

mysql性能优化(应对大量数据访问以及性能提身)

2017-04-22 21:13 627 查看
mysql性能优化的其他一些总结:

1,在join表的时候使用相当的列,将其索引

 如果你的应用程序,有很多join查询,应该确认两个表中的join字段是被建立过索引的,

这样mysql内部会启动优化join的语句。这些被用来join的字段,应该是类型相同。

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

// 在state中查找company

$r = mysql_query("SELECT company_name FROM users

    LEFT JOIN companies ON (users.state = companies.state)

    WHERE users.id = $user_id");

 

// 两个 state 字段应该是被建过索引的,而且应该是相当的类型,相同的字符集。

2,千万不能使用 order by RAND()   ——-mysql内部有RAND() 这个函数,(消耗CPU)

   

RNAD()使得mysql要每一行记录去记行,

例:

  //禁止这样

mysql_query(select * from table order by RAND() limit 1 );

//应该使用这样优化方法

$count = mysql_query( select  count(*)  from  table );

$d = mysql_fetch_row($count);

$rand = mt_rand( 0,$d-1 );

$res  =  mysql_query(  select  username  from  table  limit  $rand,1  );

3,永远为每张表设置一个ID.

在这里,只有一个情况是例外,那就是“关联表”的“外键”,也就是说,这个表的主键,通过若干个别的表的主键构成。我们把这个情况叫做“外键”。

4,使用enum而不是varchar

enum是非常快和紧凑的

5,prepared  statement

  是一种运行在后台的SQL语句集合,可以从prepare statement获取性能以及安全的好处。

prepare statement是以绑定参数的SQL,可以防止SQL注入的风险。

//创建prepared

$statement  =  $mysqli -> prepare(  "SELECT username FROM user WHERE state=?" );

//绑定参数

$statement  -> bind_param( “s” , $state);

//执行

$statement  ->  execute();

// 绑定结果

    $stmt->bind_result($username);

 

    // 移动游标

    $stmt->fetch();

 

    printf("%s is from %s

", $username, $state);

 

    $stmt->close();

6,  IP地址存成 unsigned  int 

   如果使用unsigned  int 整形存放,只需要4个字节,并且可以有定长的字段。

在查询中可以使用 inet_aton() 将一个字符串的IP转成整形,

同样使用inet_ntoa() 将整形转成字符串型IP;  在php中也有同样的函数 : ip2long()    long2ip()

$res = mysql_query(update table  set ip = inet_aton(‘{$_SERVER[‘REMOTE_ADDR’]}’))  where id=$userid;

7,垂直分割

定义:把一张表分割成几张表,这样可以降低表的复杂度和字段数目;

示例二: 你有一个叫 “last_login” 的字段,它会在每次用户登录时被更新。但是,每次更新时会导致该表的查询缓存被清空。所以,你可以把这个字段放到另一个表中,这样就不会影响你对用户ID,用户名,用户角色的不停地读取了,因为查询缓存会帮你增加很多性能。

另外,你需要注意的是,这些被分出去的字段所形成的表,你不会经常性地去Join他们,不然的话,这样的性能会比不分割时还要差,而且,会是极数级的下降。

8,拆分大的 DELETE 或 INSERT 语句

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

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

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

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

while (1) {

    //每次只做1000条

    mysql_query("DELETE FROM logs WHERE log_date <= '2009-11-01' LIMIT 1000");

    if (mysql_affected_rows() == 0) {

        // 没得可删了,退出!

        break;

    }

    // 每次都要休息一会儿

    usleep(50000);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: