我正在使用带有xdebug探测器的webgrind,我有一个AJAX请求(预留控制器中的hoursList动作),它调用func来生成预留(如果在选定日期没有)。请求需要20287毫秒,这对我来说真的很慢。我发现这里的性能bootleneck是saveMany()函数,执行需要17090毫秒。是否有更好的方法将许多记录保存到数据库中?
这是函数,它生成免费预约,在预订模型中:
public function genFreeReservations($queue_id, $sel_date) {
$this->Queue->recursive = -1;
$que = $this->Queue->findById($queue_id, array('schedule_id', 'intmins', 'location_id', 'number_id'));
//$this->Location->recirsive = 2;
$daytype = $this->Location->Specday->field('specdaytype_id', array(
"DATE_FORMAT(`spd_datetime`, '%Y-%m-%d')" => $sel_date)
);
if (!$daytype)
$daytype = 0;
$wday = CakeTime::format('N', $sel_date);
$this->Location->Interval->recursive = -1;
$intervals = $this->Location->Interval->find('all', array('conditions' => array('schedule_id' => $que['Queue']['schedule_id'],
'day' => array(0, $wday),
'Interval.specdaytype_id' => $daytype
)
)
);
$this->Queue->Number->recursive = -1;
$numbers = $this->Queue->Number->findById($que['Queue']['number_id'], array('Number.start', 'Number.end'));
$number = $numbers['Number']['start'];
$number_end = $numbers['Number']['end'];
foreach ($intervals as $interval) {
$start = CakeTime::fromString($interval['Interval']['start']);
$end = CakeTime::fromString($interval['Interval']['end']);
$resToSave = array();
while ($start < $end) {
$tend = $start + ($que['Queue']['intmins'] * 60);
for ($i = 0; $i < $interval['Interval']['workers']; $i++) {
$resToSave[] = array(
'id' => '',
'location_id' => $que['Queue']['location_id'],
'user_id' => 0,
'queue_id' => $queue_id,
'ticket_nr' => $number,
'code' => '0',
'start' => $sel_date . ' ' . CakeTime::format('H:i:s', $start),
'end' => $sel_date . ' ' . CakeTime::format('H:i:s', $tend),
'deleted' => '0',
'modified' => '0',
'synchronized' => '1'
);
if ($number == $number_end)
$number = $numbers['Number']['start'];
$number++;
}
$start = $start + ($que['Queue']['intmins'] * 60);
}
//Performance bootleneck on this function
$this->saveMany($resToSave);
}
}
saveMany函数位于此函数的末尾。
答案 0 :(得分:0)
我设法优化saveMany()函数50%的时间,我需要做的就是禁用回调函数,这可以为我使用saveMany()保存的每条记录执行:
$this->saveMany($resToSave, array('callbacks' => false));
答案 1 :(得分:0)
如果您使用CASE,您可以获得相当惊人的时间减少结果。
UPDATE `table` SET `uid` = CASE
WHEN id = 1 THEN 2952
WHEN id = 2 THEN 4925
WHEN id = 3 THEN 1592
ELSE `uid`
END
WHERE id in (1,2,3)