一 foreach的引用
$arr = range(1,3); //[1,2,3] foreach($arr as &$val) { } foreach($arr as $val) { } print_r($arr);
上面的代码会输出什么?
Array ( [0] => 1 [1] => 2 [2] => 2 )
这是因为foreach的源代码中,对变量进行了引用。导致其作用之后,将地址赋值于最后一个
例:
tmp是var的引用,指向的是var的存储空间,当tmp改变的时候,var也改变$var = 123; $tmp = &$var; $tmp = 200; echo $var;//20
示意图:
解决方法:
//方法1 foreach ($arr as &$value) { } unset($value); foreach ($arr as $value) { } print_r($arr); //[1,2,3]
//方法2 foreach ($arr as &$value) { } foreach ($arr as $val) { } print_r($arr); //[1,2,3]
//方法3 foreach ($arr as &$value) { } foreach ($arr as &$value) { } print_r($arr); //[1,2,3]
二 擅于用array_walk 和 foreach, for
<?php /** * array_walk 和 foreach, for 的效率的比较。 * 我们要测试的是foreach, for, 和 array_walk的效率的问题。 */ //产生一个10000的一个数组。 $max = 10000; $test_arr = range(0, $max); $temp; //我们分别用三种方法测试求这些数加上1的值的时间。 // for 的方法 $t1 = microtime(true); for ($i = 0; $i < $max; $i++) { $temp = $temp + 1; } $t2 = microtime(true); $t = $t2 - $t1; echo "就使用for, 没有对数组操作 花费: {$t}\n"; $t1 = microtime(true); for ($i = 0; $i < $max; $i++) { $test_arr[$i] = $test_arr[$i] + 1; } $t2 = microtime(true); $t = $t2 - $t1; echo "使用for 并且直接对数组进行了操作 花费: {$t}\n"; $t1 = microtime(true); for ($i = 0; $i < $max; $i++) { addOne($test_arr[$i]); } $t2 = microtime(true); $t = $t2 - $t1; echo "使用for 调用函数对数组操作 花费 : {$t}\n"; $t1 = microtime(true); foreach ($test_arr as $k => &$v) { $temp = $temp + 1; } $t2 = microtime(true); $t = $t2 - $t1; echo "使用 foreach 没有对数组操作 花费 : {$t}\n"; $t1 = microtime(true); foreach ($test_arr as $k => &$v) { $v = $v + 1; } $t2 = microtime(true); $t = $t2 - $t1; echo "使用 foreach 直接对数组操作 : {$t}\n"; $t1 = microtime(true); foreach ($test_arr as $k => &$v) { addOne($v); } $t2 = microtime(true); $t = $t2 - $t1; echo "使用 foreach 调用函数对数组操作 : {$t}\n"; $t1 = microtime(true); array_walk($test_arr, ‘addOne‘); $t2 = microtime(true); $t = $t2 - $t1; echo "使用 array_walk 花费 : {$t}\n"; function addOne(&$item) { $item = $item + 1; }
执行的结果:
就使用for, 没有对数组操作 花费: 0.15388584136963
使用 foreach 没有对数组操作 花费 : 0.076934814453125
使用for 并且直接对数组进行了操作 花费: 0.14769005775452
使用 foreach 直接对数组操作 : 0.076115131378174
使用for 调用函数对数组操作 花费 : 0.32393312454224
使用 foreach 调用函数对数组操作 : 0.25716996192932
使用 array_walk 花费 : 0.17966890335083
在对10000个数的操作过程中,这个实验我们可以得出这样的结论:
foreach 的效率要比for 高很多,也许有很大的一个原因是for 要进行很多次条件判断。所以以后能用foreach的地方就用foreach,可以提高1倍的效率。
如果循环内要调用函数,用array_walk 最好,它的效率要比for 高出1倍,要比foreach高出43%的效率。
还有一个提示就是如果你这个程序对效率的要求是很高的,那不要在很深的循环中调用函数,要调用函数也要用array_walk,最好的直接把代码写在循环里面。
同时,我们来看一下这两个函数的区别:
array_walk 主要是要对数组内的每个值进行操作,操作结果影响原来的数组 array_map主要是对数组中的值进行操作后返回数组,以得到一个新数组 wallk 可以没有返回值 map要有,因为要填充数组
三 为什么要用联合索引 ?
1 在多条件查询时,联合索引效率要高。在允许的范围内,多条件个条件查询的时候,应该根据业务创建多个联合索引。这样效率比分开创建多个索引要快
2 查询条件中出现联合索引第一列,或者全部,则能利用联合索引.
换句话说:查询条件中没有出现联合索引的第一列,而出现联合索引的第二列,或者第三列,都不会利用联合索引查询.
而单一索引:只要条件列中出现索引列,无论在什么位置,都能利用索引查询.
我本地电脑有如下表:
CREATE TABLE `t_log_change_name` ( `id` int(11) NOT NULL AUTO_INCREMENT, `player_id` int(11) NOT NULL DEFAULT ‘0‘, `old_name` varchar(255) NOT NULL DEFAULT ‘‘, `day` int(11) NOT NULL DEFAULT ‘20110101‘, PRIMARY KEY (`id`), KEY `idx_player_id` (`player_id`,`day`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
当我使用联合条件查询,
EXPLAIN select * from t_log_change_name where player_id =344 and `day`>=‘20161012‘;
结果当然是没问题的,直接选中想要的数据,影响行为3行
当我用只使用第一列为条件查询,
EXPLAIN select * from t_log_change_name where player_id =344;
它处于索引的第一列,因此是可以命中索引的
当我使用第二列为条件查询,
EXPLAIN select * from t_log_change_name where `day`>=‘20161012‘;
那不好意思,它属于索引的第二列,因此无法命中索引,全部行都检索一遍
所以务必根据业务需求而去建立合适的索引
,同时注意联合索引的顺序,失效情况。