- php变量用完后主动释放
$variable = null;
- 单引号包含字符串或数组下标比双引号快,因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会。
$variable = ‘content’;
$array[‘key’] = ‘content’;
- 在包含文件时使用完整路径,解析操作系统路径所需的时间会更少。
include(‘/path/to/absolute/test.php’)
>require更快,include有返回值
- 用require
代替require_once
>requiere_once()比较耗资源;
>这为requiere_once需要判断该文件是否被引用过,所以能不用尽量不用。使用require/include方法代替。
- 递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。
- str_replace
比preg_replace
快,但strtr
比str_replace
要快4倍。
>具体使用视场景而定
- 使用选择分支语句(译注:即switch case)好于使用多个if,else if语句。
>当分支判断较多时使用switch,更重要的一点是:易读。
- 递增一个全局变量要比递增一个局部变量慢2倍。
- implode()
代替.=
拼接
$array = array(‘abc’, ‘def’, ‘ghi’);
$comma_separated = implode(’’,$array);
替换下面的代码:
$array = array(‘abc’, ‘def’, ‘ghi’);
$comma_separated = ’’;
foreach ($array as $value){
$comma_separated .= $value;
}
- 用i+=1代替i=i+1
- 用file_put_contents/file_get_contents
代替fopen、fread、fclose
系列文件操作函数
- 使用php内置的filter来代替正则验证邮箱、ip、url等.
$email = ’test@imihuan.com';
$email = filter_var($email,FILTER_VALIDATE_EMAIL)?:’’; //test@imihuan.com
$ip = ‘192.168.1.aa’
$ip = filter_var($ip,FILTER_VALIDATE_IP)?:’’; //false
- 使用php内置字符串函数替换字符串正则匹配
pregmatch(“/^foo/i“, ”FoO_")
!strncasecmp(“foo“, ”FoO”, 4) #ok
preg_replace(“/\n/”,“\n”,‘hello’);
str_replace(“/\n/”,“\n”,‘hello’); #ok
>strcasecmp
或者strncasecmp
比较字符串,相等返回0,
- 使用array_filter
判断二维数组是否都为空:
$arr= array(array(),array(),array());
$temp = array_filter($arr) ;
if(!empty($temp)){
print_r($temp);
}else{
echo ‘二维数组都为空’;
}
- 连接变量比放在双引号中更快
$var = ‘Hello ’ . $world; // 最快
$var = “Hello $world”;
$var = “Hello {$world}”;
- 使用===
>使用===
而不是==
,因为前者严格检查封闭范围,使其更快。
- 如果逻辑允许,使用引用来遍历数组,减少副本的创建。
foreach($array as &$value){}
function fun(&$var){}
- 主要判断放在顶部
- 继承关系中,同样的操作,子类方法比基类方法快。
- 使用isset
使用isset()
尽可能不使用count()
,strlen()
,sizeof()
来检查返回的值是否大于0。
- 使用sprintf
$num = 5;
$location = ‘tree’;
$format = ‘There are %d monkeys in the %s’;
echo sprintf($format, $num, $location);
>使用sprintf要比替换双引号中替换变量要快十倍。
- echo , print
>echo $a, $b, $c;比速度快echo $a . $b . $c;,但echo $a . $b . $c;比速度快print $a . $b . $c。
- 使用选择分支语句
>switch case好于使用多个if,else if语句,并且代码更加容易阅读和维护。
- foreach效率更高,尽量用foreach代替while和for循环
- 对global
变量,应该用完就unset()
掉
function destroy_foo()
{
global $foo;
unset($foo);
}
function __destruct() {
unset($this->variable);
}
- 并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。
- 不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?
- explode()
比split()
快
>explode用字符串分割,split用正则分割.
- 能用PHP内部字符串操作函数的情况下,尽量用他们,不要用正则表达式; 效率高于正则;
strtr — 转换指定字符
substr — 返回字符串的子串
ucfirst — 将字符串的首字母转换为大写
ucwords — 将字符串中每个单词的首字母转换为大写
strpbrk — 在字符串中查找一组字符的任何一个字符
printf — 输出格式化字符串
strtr — 转换指定字符
strstr — 查找字符串的首次出现,返回字符串
strpos — 查找字符串首次出现的位置
strrchr — 查找指定字符在字符串中的最后一次出现
strrev — 反转字符串
str_pad — 使用另一个字符串填充字符串为指定长度
str_split — 将字符串转换为数组
。。。。。
- 使用ip2long()和long2ip()函数把IP地址转成整型存放进数据库而非字符型。
$ip = ‘172.16.1.34’;
$long = ip2long($ip);
var_dump($long);//int(-1408237278)
>注意,ip2long(),转换ip后是一个有符号的整型。
>这几乎能降低1/4的存储空间。同时可以很容易对地址进行排序和快速查找;
- 减少变量复制
$val = $_POST[‘name’];
echo $val;
————
echo $_POST[‘name’];
- 将计算放在循环外
for ($i = 0; $i < count($my_array); $i++) #no
for ($i = 0, $count = count($my_array); $i < $count; $i++) #ok
#或者
$count = count($my_array);
for ($i = 0; $i < $count; $i++) #ok
- 避免使用如下魔术方法
__set
__get
__call
- 替换如下函数调用
time() - $_SERVER[‘REQUEST_TIME’]
phpversion() - PHP_VERSION
getclass() - CLASS_
is_null() - NULL ===
strlen($str) >= 5 – isset($str{5})
print() - echo
- 使用引用
$a[1][2] = array();
for($i = 0; $i < 10; $i++)
$a[1][2][$i] = $i;
?>
———-使用如下代码替换————-
$ref =& $a[1][2];
for($i = 0; $i < 10; $i++)
$ref[$i] = $i;
?>
- 使用PHPDoc注释规范
1.文件
/**
* XXXXX的文件
*
* 功能1: xxx
* 功能2: xxx
*
* @file $Source: /home/doc/php开发注释规范.md $
* @package core
* @author test test@imihuan.com
* @link http://www.github.com
*/
2.类
/**
* xxxxx类
*
* 功能1:完成xxxx
* 功能2:完成xxxxx
*
* @author test test@imihuan.com
* @access public
* @abstract
*/
3.方法
/**
* 获取一条商品详情
*
* @param int $id 商品id
* @return array 商品详情
*/
>更多标签参考,参考phpdoc官网:https://www.phpdoc.org/docs/latest/index.html
sql部分
- 经常同时存取多列,且每列都含有重复值可考虑建立组合索引, 选择度高的列建议作为索引的第一个字段
- 应尽量避免在 where
子句中使用!=
或<>
操作符,否则将引擎放弃使用索引而进行全表扫描。
- 避免字段进行null
值判断,如where num is null
;
- 对于连续的值用,between..and代替in()
>in()
长度没有限制,但是sql语句有长度限制,默认1M,通过/etc/my.cnf
max_allowed_packet = 6M
,来进行修改
- 应尽量避免在 where 子句中对字段进行表达式操作, 这将导致引擎放弃使用索引而进行全表扫描。
select id from t where num=100*2; # ok
select id from t where num/2=100;
- 应尽量避免在 where 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
select * from product_info WHERE SUBSTRING(name,1,4) = ‘采购商品’; #no
- 很多时候用 exists 代替 in 是一个好的选择:
select id from product_info where id in(SELECT product_id from product_detail) ; #no
select id from product_info where EXISTS(SELECT product_id from product_detail) ;#ok
- 使用批量插入,但是也不要太大,因为会锁表。
- 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
- 尽量避免大事务操作,提高系统并发能力。
- OPTIMIZE
>OPTIMIZE TABLE table_name
优化表
>
>一旦数据达到稳定的大小,或者增长的表已经增加了几十或几百兆字节,使用该OPTIMIZE TABLE语句来重组表并压缩任何浪费的空间。
>
>OPTIMIZE TABLE 用于回收闲置的数据库空间,当表上的数据行被删除时,所占据的磁盘空间并没有立即被回收,
>使用了OPTIMIZE TABLE命令后这些空间将被回收,并且对磁盘上的数据行进行重排(注意:是磁盘上,而非数据库)。
>innodb不支持,,,,
- 分析表ANALYZE
ANALYZE TABLE store_inventory
![](http://i.imgur.com/eSWU06F.png)
>Analyze 用来分析和存储表的关键字的分布,使得系统获得准确的统计信息,影响 SQL 的执行计划的生成。
>对于数据基本没有发生变化的表,是不需要经常进行表分析的。
- check
CHECK TABLE allocate_storage
>CHECK TABLE检查表或表是否有错误。对于MyISAM表格,关键统计信息也会更新。CHECK TABLE还可以查看问题的视图,例如在视图定义中引用的不再存在的表。
- 使用PROCEDURE ANALYZE
SELECT * FROM product_info PROCEDURE ANALYSE(50000)
>PROCEDURE ANALYZE会给出字段设置、优化建议,列出最佳数据类型,
![](http://i.imgur.com/iH4HMva.png)
- 使用EXPLAIN查看select语句
- 只要一条数据时加上limit 1
- 判断记录是否存在用select 1 from table 代替 select * from table
- 删除表记录速度: truncate > delete
- 被用来Join的字段,应该是相同的类型的,而且关联的字段都应建立索引
- 字段尽可能的使用 NOT NULL约束,如果一定要用NULL,尽量用0代替
- 不要建立冗余索引如:(a,b,c)、(a,b)
- where条款优化
1.删除不必要的括号:
((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)
2.ORDER BY和GROUP BY子句中的所有列最好来自同一个表
3.如果一定要使用临时表,对于较大的临时表使用SQL_BIG_REQUEST
,较小的临时表使用SQL_SMALL_REQUEST
SELECT
a.id,a.name,a.product_code,d.photo_id
FROM product_info a
LEFT JOIN (SELECT SQL_BIG_RESULT min(photo_id) photo_id from photo_link GROUP BY product_id) d ON a.id = d.photo_id
WHERE
a.company_id =‘5053’
4.使用ALL, DISTINCT和DISTINCTROW选项指定是否重复行应被返回。
5.常量重叠
(a
-> b>5 AND b=c AND a=5
6.去除常量条件:
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6
>(B>=5 AND B=5) –>B=5
>
>(B=6 AND 5=5) –>B=6
>
>(B=7 AND 5=6) –>FALSE
7.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
SELECT price_trade,price_cost,weight FROM product_detail WHERE weight/2=0.2
SELECT price_trade,price_cost,weight FROM product_detail WHERE weight=0.4 #ok
- 索引并不是越多越好,一个表的索引数最好不要超过6个。
- 尽量使用数字型字段,可查询和连接的性能,并会减少存储开销。这是因为mysql在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
is_delete enum(0,1)
- 合并可以join的查询
$query = mysql_query(“SELECT id FROM your_table”);
while ($row = mysql_fetch_assoc($query)) {
$query2 = mysql_query(“SELECT * FROM your_other_table WHERE id = {$row[‘id’]}”);
}
>这是一条简单的innner join
查询
- 参考:
https://dev.mysql.com/doc/refman/5.7/en/procedure-analyse.html
https://blog.appdynamics.com/engineering/php-performance-crash-course-part-1-the-basics/
https://stackoverflow.com/questions/4195937/what-are-some-good-php-performance-tips
http://www.thegeekstuff.com/2014/04/optimize-php-code
http://phplens.com/lens/php-book/optimizing-debugging-php.php
http://www.alexhe.org/php/2015-11-24/2294.html
http://www.sohu.com/a/134630650_609569
# php & mysql代码优化建议#
- php变量用完后主动释放
$variable = null;
- 单引号包含字符串或数组下标比双引号快,因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会。
$variable = 'content';
$array['key'] = 'content';
- 在包含文件时使用完整路径,解析操作系统路径所需的时间会更少。
include('/path/to/absolute/test.php')
>require更快,include有返回值
- 用`require`代替`require_once`
>requiere_once()比较耗资源;
>这为requiere_once需要判断该文件是否被引用过,所以能不用尽量不用。使用require/include方法代替。
- 递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。
- `str_replace`比`preg_replace`快,但`strtr`比`str_replace `要快4倍。
>具体使用视场景而定
- 使用选择分支语句(译注:即switch case)好于使用多个if,else if语句。
>当分支判断较多时使用switch,更重要的一点是:易读。
- 递增一个全局变量要比递增一个局部变量慢2倍。
- `implode()`代替`.=`拼接
$array = array('abc', 'def', 'ghi');
$comma_separated = implode('',$array);
替换下面的代码:
$array = array('abc', 'def', 'ghi');
$comma_separated = '';
foreach ($array as $value){
$comma_separated .= $value;
}
- 用i+=1代替i=i+1
- 用`file_put_contents/file_get_contents`代替`fopen、fread、fclose`系列文件操作函数
- 使用php内置的filter来代替正则验证邮箱、ip、url等.
$email = 'test@imihuan.com';
$email = filter_var($email,FILTER_VALIDATE_EMAIL)?:''; //test@imihuan.com
$ip = '192.168.1.aa'
$ip = filter_var($ip,FILTER_VALIDATE_IP)?:''; //false
- 使用php内置字符串函数替换字符串正则匹配
preg_match(“/^foo_/i", "FoO_")
!strncasecmp("foo_", "FoO_", 4) #ok
preg_replace("/\n/","\\n",'hello');
str_replace("/\n/","\\n",'hello'); #ok
>`strcasecmp`或者`strncasecmp`比较字符串,相等返回0,
- 使用`array_filter`判断二维数组是否都为空:
$arr= array(array(),array(),array());
$temp = array_filter($arr) ;
if(!empty($temp)){
print_r($temp);
}else{
echo '二维数组都为空';
}
- 连接变量比放在双引号中更快
$var = 'Hello ' . $world; // 最快
$var = "Hello $world";
$var = "Hello {$world}";
- 使用`===`
>使用`===`而不是`==`,因为前者严格检查封闭范围,使其更快。
- 如果逻辑允许,使用引用来遍历数组,减少副本的创建。
foreach($array as &$value){}
function fun(&$var){}
- 主要判断放在顶部
- 继承关系中,同样的操作,子类方法比基类方法快。
- 使用`isset`
使用`isset()`尽可能不使用`count()`,`strlen()`,`sizeof()`来检查返回的值是否大于0。
- 使用sprintf
$num = 5;
$location = 'tree';
$format = 'There are %d monkeys in the %s';
echo sprintf($format, $num, $location);
>使用sprintf要比替换双引号中替换变量要快十倍。
- echo , print
>echo $a, $b, $c;比速度快echo $a . $b . $c;,但echo $a . $b . $c;比速度快print $a . $b . $c。
- 使用选择分支语句
>switch case好于使用多个if,else if语句,并且代码更加容易阅读和维护。
- foreach效率更高,尽量用foreach代替while和for循环
- 对`global`变量,应该用完就`unset()`掉
function destroy_foo()
{
global $foo;
unset($foo);
}
function __destruct() {
unset($this->variable);
}
- 并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。
- 不要把方法细分得过多,仔细想想你真正打算重用的是哪些代码?
- `explode()`比`split()`快
>explode用字符串分割,split用正则分割.
- 能用PHP内部字符串操作函数的情况下,尽量用他们,不要用正则表达式; 效率高于正则;
strtr — 转换指定字符
substr — 返回字符串的子串
ucfirst — 将字符串的首字母转换为大写
ucwords — 将字符串中每个单词的首字母转换为大写
strpbrk — 在字符串中查找一组字符的任何一个字符
printf — 输出格式化字符串
strtr — 转换指定字符
strstr — 查找字符串的首次出现,返回字符串
strpos — 查找字符串首次出现的位置
strrchr — 查找指定字符在字符串中的最后一次出现
strrev — 反转字符串
str_pad — 使用另一个字符串填充字符串为指定长度
str_split — 将字符串转换为数组
。。。。。
- 使用ip2long()和long2ip()函数把IP地址转成整型存放进数据库而非字符型。
$ip = '172.16.1.34';
$long = ip2long($ip);
var_dump($long);//int(-1408237278)
>注意,ip2long(),转换ip后是一个有符号的整型。
>这几乎能降低1/4的存储空间。同时可以很容易对地址进行排序和快速查找;
- 减少变量复制
$val = $_POST['name'];
echo $val;
------------
echo $_POST['name'];
- 将计算放在循环外
for ($i = 0; $i < count($my_array); $i++) #no
for ($i = 0, $count = count($my_array); $i < $count; $i++) #ok
#或者
$count = count($my_array);
for ($i = 0; $i < $count; $i++) #ok
- 避免使用如下魔术方法
__set
__get
__call
- 替换如下函数调用
time() - $_SERVER['REQUEST_TIME']
phpversion() - PHP_VERSION
get_class() - __CLASS__
is_null() - NULL ===
strlen($str) >= 5 – isset($str{5})
print() - echo
- 使用引用
$a[1][2] = array();
for($i = 0; $i < 10; $i++)
$a[1][2][$i] = $i;
?>
----------使用如下代码替换-------------
$ref =& $a[1][2];
for($i = 0; $i < 10; $i++)
$ref[$i] = $i;
?>
- 使用PHPDoc注释规范
1.文件
/**
* XXXXX的文件
*
* 功能1: xxx
* 功能2: xxx
*
* @file $Source: /home/doc/php开发注释规范.md $
* @package core
* @author test
* @link http://www.github.com
*/
2.类
/**
* xxxxx类
*
* 功能1:完成xxxx
* 功能2:完成xxxxx
*
* @author test
* @access public
* @abstract
*/
3.方法
/**
* 获取一条商品详情
*
* @param int $id 商品id
* @return array 商品详情
*/
>更多标签参考,参考phpdoc官网:[https://www.phpdoc.org/docs/latest/index.html](https://www.phpdoc.org/docs/latest/index.html)
**sql部分**
- 经常同时存取多列,且每列都含有重复值可考虑建立组合索引, 选择度高的列建议作为索引的第一个字段
- 应尽量避免在 `where `子句中使用`!=`或`<>`操作符,否则将引擎放弃使用索引而进行全表扫描。
- 避免字段进行`null`值判断,如`where num is null`;
- 对于连续的值用,between..and代替in()
>`in()`长度没有限制,但是sql语句有长度限制,默认1M,通过`/etc/my.cnf` `max_allowed_packet = 6M`,来进行修改
- 应尽量避免在 where 子句中对字段进行表达式操作, 这将导致引擎放弃使用索引而进行全表扫描。
select id from t where num=100*2; # ok
select id from t where num/2=100;
- 应尽量避免在 where 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
select * from product_info WHERE SUBSTRING(`name`,1,4) = '采购商品'; #no
- 很多时候用 exists 代替 in 是一个好的选择:
select id from product_info where id in(SELECT product_id from product_detail) ; #no
select id from product_info where EXISTS(SELECT product_id from product_detail) ;#ok
- 使用批量插入,但是也不要太大,因为会锁表。
- 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
- 尽量避免大事务操作,提高系统并发能力。
- OPTIMIZE
>OPTIMIZE TABLE `table_name` 优化表
>
>一旦数据达到稳定的大小,或者增长的表已经增加了几十或几百兆字节,使用该OPTIMIZE TABLE语句来重组表并压缩任何浪费的空间。
>
>OPTIMIZE TABLE 用于回收闲置的数据库空间,当表上的数据行被删除时,所占据的磁盘空间并没有立即被回收,
>使用了OPTIMIZE TABLE命令后这些空间将被回收,并且对磁盘上的数据行进行重排(注意:是磁盘上,而非数据库)。
>innodb不支持,,,,
- 分析表ANALYZE
ANALYZE TABLE store_inventory
![](http://i.imgur.com/eSWU06F.png)
>Analyze 用来分析和存储表的关键字的分布,使得系统获得准确的统计信息,影响 SQL 的执行计划的生成。
>对于数据基本没有发生变化的表,是不需要经常进行表分析的。
- check
CHECK TABLE allocate_storage
>CHECK TABLE检查表或表是否有错误。对于MyISAM表格,关键统计信息也会更新。CHECK TABLE还可以查看问题的视图,例如在视图定义中引用的不再存在的表。
- 使用PROCEDURE ANALYZE
SELECT * FROM product_info PROCEDURE ANALYSE(50000)
>PROCEDURE ANALYZE会给出字段设置、优化建议,列出最佳数据类型,
![](http://i.imgur.com/iH4HMva.png)
- 使用EXPLAIN查看select语句
- 只要一条数据时加上`limit 1`
- 判断记录是否存在用select 1 from table 代替 select * from table
- 删除表记录速度: `truncate > delete`
- 被用来Join的字段,应该是相同的类型的,而且关联的字段都应建立索引
- 字段尽可能的使用 NOT NULL约束,如果一定要用NULL,尽量用0代替
- 不要建立冗余索引如:(a,b,c)、(a,b)
- where条款优化
1.删除不必要的括号:
((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)
2.ORDER BY和GROUP BY子句中的所有列最好来自同一个表
3.如果一定要使用临时表,对于较大的临时表使用`SQL_BIG_REQUEST`,较小的临时表使用`SQL_SMALL_REQUEST`
SELECT
a.id,a.`name`,a.product_code,d.photo_id
FROM product_info a
LEFT JOIN (SELECT SQL_BIG_RESULT min(photo_id) photo_id from photo_link GROUP BY product_id) d ON a.id = d.photo_id
WHERE
a.company_id ='5053'
4.使用ALL, DISTINCT和DISTINCTROW选项指定是否重复行应被返回。
5.常量重叠
(a
-> b>5 AND b=c AND a=5
6.去除常量条件:
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
-> B=5 OR B=6
>(B>=5 AND B=5) -->B=5
>
>(B=6 AND 5=5) -->B=6
>
>(B=7 AND 5=6) -->FALSE
7.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
SELECT price_trade,price_cost,weight FROM product_detail WHERE weight/2=0.2
SELECT price_trade,price_cost,weight FROM product_detail WHERE weight=0.4 #ok
- 索引并不是越多越好,一个表的索引数最好不要超过6个。
- 尽量使用数字型字段,可查询和连接的性能,并会减少存储开销。这是因为mysql在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
is_delete enum(0,1)
- 合并可以join的查询
$query = mysql_query("SELECT id FROM your_table");
while ($row = mysql_fetch_assoc($query)) {
$query2 = mysql_query("SELECT * FROM your_other_table WHERE id = {$row['id']}");
}
>这是一条简单的`innner join`查询
- 参考:
[https://dev.mysql.com/doc/refman/5.7/en/procedure-analyse.html](https://dev.mysql.com/doc/refman/5.7/en/procedure-analyse.html "mysql官方文档")
[https://blog.appdynamics.com/engineering/php-performance-crash-course-part-1-the-basics/](https://blog.appdynamics.com/engineering/php-performance-crash-course-part-1-the-basics/)
[https://stackoverflow.com/questions/4195937/what-are-some-good-php-performance-tips](https://stackoverflow.com/questions/4195937/what-are-some-good-php-performance-tips)
[http://www.thegeekstuff.com/2014/04/optimize-php-code](http://www.thegeekstuff.com/2014/04/optimize-php-code)
[http://phplens.com/lens/php-book/optimizing-debugging-php.php](http://phplens.com/lens/php-book/optimizing-debugging-php.php)
[http://www.alexhe.org/php/2015-11-24/2294.html](http://www.alexhe.org/php/2015-11-24/2294.html)
[http://www.sohu.com/a/134630650_609569](http://www.sohu.com/a/134630650_609569 "50多条实用mysql数据库优化建议")