我有一个 Codeigniter 系统,用户可以在其中输入约会并让它每周自动重复一次。如果原始约会设置为重复,系统会自动在当前日期前一个月创建约会。
这里是模块函数。它有效,但男孩是不是很慢。非常感谢建议;有没有办法使用 SQL 在几次传递中完成此操作?
问题是嵌套循环,当系统有数百个重复约会来检查时,运行大约需要 20 秒。
对于重复的约会,“重复”字段设置为 1,对于从它创建的“子”约会,设置为 2。
function update_repeat_appointments($pupil_ID=NULL) // adds appointments 1 month ahead for all repeat appointments
{
if ($pupil_ID != NULL) {$this->db->where('timetable.pupil_ID', $pupil_ID);}
$this->db->where('repeats', 1);
$this->db->where('date >=', date('Y-m-d', strtotime("-1 month", strtotime("now"))));
$this->db->order_by("date", "asc");
$query = $this->db->get('timetable');
$repeatapps = $query->result();
$enddate = strtotime("+1 month", strtotime("now")); // Change this line to have repeat appointments go further into the future
//Loop over current repeat appointments
foreach ($repeatapps as $row) {
$startdate = strtotime($row->date);
$runningdate = $startdate;
$this->db->where('pupil_id', $row->pupil_id);
$this->db->where('repeats <>', 1);
$this->db->where('date >=', date('Y-m-d', strtotime("-1 month", strtotime("now"))));
$this->db->order_by("date", "asc");
$query = $this->db->get('timetable');
$subapps = $query->result();
while ($runningdate <= $enddate) {
// Check if there is an appointment in a future week for this pupil
$runningdate = strtotime("+1 week", $runningdate);
$found=false;
foreach ($subapps as $subrow) {
if (strtotime($subrow->date) == $runningdate) { //Matched appointment found, exit loop
$found=true;
break;
}
}
if ($found=false) {
//Add an appointment with relevant data, including future date
$data = array ( "staff_id" => $row->staff_id,
"pupil_id" => $row->pupil_id,
"venue_id" => $row->venue_id,
"group_id" => $row->group_id,
"notes" => $row->notes,
"date" => date('Y-m-d h:i:s', $runningdate),
"repeats" => 2, // is a sub_repeat
"root_ID" => $row->ID // Record ID of root appointment, allows bulk changes to it's repeats
);
$this->add_appointment($data);
}
}
}
最佳答案
这似乎不是“这个特定脚本很慢”的问题,而是“这个特定脚本无法扩展,因为它一次做太多事情”的问题。
我会假设这是一个 cron 脚本。它必须重新计算信息,无论是否有任何变化。您拥有的重复事件越多,此脚本花费的时间就越长。
我会问一些这样的问题:
- 我可以在约会标记为重复时提前一个月填充吗? (负载分配给请求操作的各个用户)
- 我能否在每次旧事件通过时附加一个新事件,从而保留一个月值(value)的运行列表,但不必每次都进行昂贵的计算? (负载可能集中在此处的 cron 脚本中,除非您有相关用户触发的“事件”——即标记为参加/完成/等)
在这种情况下,cron 逻辑如下:
- 检查自上次 cron 脚本运行以来已经过去的重复约会(某种“已处理”标志)
- 对于每条通过的约会记录,在循环间隔内将一条记录添加到队列末尾,并将“过期”记录标记为“已处理”
话虽如此,20 秒的 cron 脚本并不像 20 秒的页面请求那么糟糕。分配负载时,始终倾向于用户体验。
关于php - 加速创造 future 记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9128497/