Model::saveMany()在CakePHP 2.4上执行速度非常慢
我正在将webgrind与xdebug profiler一起使用,我在Reservations Controller中有一个AJAX requesthoursList操作,它调用func生成Reservations,如果在所选日期没有要显示的内容。请求需要20287毫秒,这对我来说非常慢。我发现这里的performance bootleneck是saveMany函数,它需要17090毫秒才能执行。是否有更好的方法将许多记录保存到数据库中 以下是生成免费预订的函数,它位于预订模型中:Model::saveMany()在CakePHP 2.4上执行速度非常慢,cakephp,optimization,cakephp-2.4,Cakephp,Optimization,Cakephp 2.4,我正在将webgrind与xdebug profiler一起使用,我在Reservations Controller中有一个AJAX requesthoursList操作,它调用func生成Reservations,如果在所选日期没有要显示的内容。请求需要20287毫秒,这对我来说非常慢。我发现这里的performance bootleneck是saveMany函数,它需要17090毫秒才能执行。是否有更好的方法将许多记录保存到数据库中 以下是生成免费预订的函数,它位于预订模型中: public
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函数位于该函数的末尾。我成功地将saveMany函数优化了50%,我所需要做的就是禁用回调函数,可以使用saveMany对我保存的每条记录执行回调函数:
$this->saveMany($resToSave, array('callbacks' => false));
若你们使用这个用例,你们可以得到非常惊人的减少时间的结果
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)
你保存了多少记录?saveMany以前从未给过我一个问题,所以我假设还有其他问题。这里有780条记录,有没有更快的方法?首先定义slow,然后使用xdebugs profiler找出php堆栈中的瓶颈确切来源。但是考虑到您保存的行的数量,我倾向于说这可能是正常的,或者DB很慢。现在,当使用saveMany时,它将为您保存的每条记录触发所有模型回调。如果您不需要这里的回调,请禁用它们。您也可以尝试构建单个模型->查询。我通常不喜欢对用户生成的内容执行此操作,但看起来这不是您要保存的内容。在这种情况下,单个/大型多个插入可能会更好。禁用回调,但它似乎工作得更快一些。如果我有任何问题,我会写信给明天。