Dai Chong's blog

今天来写一篇如何优化在循环里的sql。相信大家都会遇到在foreach里循环操作数据库,上学的时候一听到循环查表这类的词,哇!感觉很高端,殊不知这样的操作对数据库的压力是无限大的。像一个三级的分类数据操作,很多人会选择循环查表,毕竟这样的写法是最方便、最简单的。前期数据量小的时候是没有很明显的问题,到了一定程度,你会发现页面加载速度越来越慢,数据库的压力越来越大。这个时候你必须要选择修改你的程序了!

但是这篇文章不是来介绍如何优化循环查询的,是介绍如何来优化循环修改表数据的。

下面介绍一下我正在做的一些业务:

数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Array
(
[0] => Array
(
[did] => 1446175
[userid] => 449310
[danhao] => W1808100219
[isno] => 2
[green_state] => R
[id] => 19
[time] => 2018-08-10 11:06:30
)

[1] => Array
(
[did] => 1446174
[userid] => 456791
[danhao] => W1808100218
[isno] => 2
[green_state] => R
[id] => 34
[time] => 2018-08-10 11:06:30
)

[2] => Array
(
[did] => 1446172
[userid] => 113637
[danhao] => W1808100217
[isno] => 2
[green_state] => R
[id] => 38
[time] => 2018-08-10 11:06:30
)

[3] => Array
(
[did] => 1446171
[userid] => 10884
[danhao] => W1808100216
[isno] => 2
[green_state] => R
[id] => 5
[time] => 2018-08-10 11:06:30
)

[4] => Array
(
[did] => 1446169
[userid] => 79165
[danhao] => W1808100214
[isno] => 2
[green_state] => R
[id] => 11
[time] => 2018-08-10 11:06:30
)

)

code snippet

这个功能的要求是同步订单,数据就像上边展示的一样 green_state 的值是不固定的,可能是R也可能是X,这个代表的是订单的状态。
我现在要做的是拿这个订单状态去把他相应的字段值改成这个状态。

原始写法:循环修改

逻辑
1
2
3
foreach($order as $k=>$v){
Db::query("update order set green_state=$v['green_state'] set did=$v['did']");
}

这样的写法有多少条数据就会请求数据库多少次,无疑是最消耗性能的写法。

优化写法:链接sql


逻辑代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//预定sql s
$Rsql = '';
$RsetIds = '';
//e
//取消sql s
$Xsql = '';
$XsetIds = '';
//e
//I
$Isql = '';
$IsetIds = '';
//
//O
$Osql = '';
$OsetIds = '';
//
//N
$Nsql = '';
$NsetIds = '';
//
//D
$Dsql = '';
$DsetIds = '';
//
foreach ($order_data as $k => $v) {
$order_data[$k]['time'] = date('Y-m-d H:i:s');
$data = json_decode($this->order_info($pms['url'],$pms['jiudian'],$pms['hotelgroupId'],$v['danhao']),true);
if($data['resultCode']==0){
$order_data[$k]['green_state'] = $data['guest']['sta'];
}
//组合sql R类型 预定
if($order_data[$k]['green_state']=='R'){
$Rsql = "set green_state='R'";
$RsetIds .= $v['did'].',';
}
//组合sql X类型 取消
if($order_data[$k]['green_state']=='X'){
$Xsql = "set green_state='X'";
$XsetIds .= $v['did'].',';
}
//组合sql I类型 在住
if($order_data[$k]['green_state']=='I'){
$Isql = "set green_state='I'";
$IsetIds .= $v['did'].',';
}
//组合sql O类型 退房
if($order_data[$k]['green_state']=='O'){
$Osql = "set green_state='O'";
$OsetIds .= $v['did'].',';
}
//组合sql N类型 应到未到
if($order_data[$k]['green_state']=='N'){
$Nsql = "set green_state='N'";
$NsetIds .= $v['did'].',';
}
//组合sql D类型 删除
if($order_data[$k]['green_state']=='D'){
$Dsql = "set green_state='D'";
$DsetIds .= $v['did'].',';
}
}
$RsetIds = trim($RsetIds,',');
$XsetIds = trim($XsetIds,',');
$IsetIds = trim($IsetIds,',');
$OsetIds = trim($OsetIds,',');
$NsetIds = trim($NsetIds,',');
$DsetIds = trim($DsetIds,',');
$sql = "update order $Rsql where did in($RsetIds)";

以上就是我根据需求调整的代码,通过不同订单类型组成不同的sql,最终实现6条sql完成6个类型的修改,如果是10w条数据,那么请求数据库的次数是6次,相比之前的次数降低了9千多次!达到了优化的效果,当然这个代码还有优化的空间。
以上代码只是为大家提供思路,具体业务逻辑还要根据实际情况而定!


 评论