【发布时间】:2017-11-08 08:04:19
【问题描述】:
我在从大量 MySQL 数据库中获取数据时遇到问题。
使用下面的代码可以获取 10K 患者和 5K 预约的列表,这是我们的测试服务器。
但是,在我们的实时服务器上,患者数量超过 100K,预约数量超过 300K,当我运行代码一段时间后,它会出现 500 错误。
我需要患者的治疗状态为 1 或 3 并且在上次预约后一个月内没有预约的患者列表。 (以下代码适用于少量患者和预约)
如何优化第一个数据库查询,以便在 foreach 循环中不需要第二个数据库查询?
<?php
ini_set('memory_limit', '-1');
ini_set('max_execution_time', 0);
require_once('Db.class.php');
$patients = $db->query("
SELECT
p.id, p.first_name, p.last_name, p.phone, p.mobile,
LatestApp.lastAppDate
FROM
patients p
LEFT JOIN (SELECT patient_id, MAX(start_date) AS lastAppDate FROM appointments WHERE appointment_status = 4) LatestApp ON p.id = LatestApp.patient_id
WHERE
p.patient_treatment_status = 1 OR p.patient_treatment_status = 3
ORDER BY
p.id
");
foreach ($patients as $row) {
$one_month_after_the_last_appointment = date('Y-m-d', strtotime($row['lastAppDate'] . " +1 month"));
$appointment_check = $db->single("SELECT COUNT(id) FROM appointments WHERE patient_id = :pid AND appointment_status = :a0 AND (start_date >= :a1 AND start_date <= :a2)", array("pid"=>"{$row['id']}","a0"=>"1","a1"=>"{$row['lastAppDate']}","a2"=>"$one_month_after_the_last_appointment"));
if($appointment_check == 0){
echo $patient_id = $row['id'].' - '.$row['lastAppDate'].' - '.$one_month_after_the_last_appointment. '<br>';
}
}
?>
【问题讨论】:
-
如果是我,我会暂时摆脱所有的 php,而专注于 sql。如果您同意,请参阅meta.stackoverflow.com/questions/333952/…
-
理想情况下,您不应运行两个查询——尤其是循环中的一个。
-
我认为速度问题与子查询和LEFT JOIN有关。我认为您最好使用 INNER JOIN 来加快查询速度,删除您的子查询,正常 JOINING 另一个表,并按约会 id (如果有)使用分组,并在使用 MAX 的选择中获取最新约会.
标签: php mysql query-optimization