大量のMySQLデータベースからデータを取得する際に問題が発生しています。大量のMySQLデータベースからデータを取得するためにSQLクエリを最適化する
以下のコードで、私たちのテストサーバーである10K患者と5K予定のリストを取得することは大丈夫です。
しかし私たちのライブサーバーでは、患者数は100Kを超え、予定数は300Kを超えています。しばらくしてからコードを実行すると、500のエラーが発生します。
patient_treatment_statusが1または3であり、最後の予約から1ヶ月後に予定がない患者のリストが必要です。 (以下のコードは、少量の患者と予定に対応しています)
foreachループで2番目のデータベースクエリが不要になるように、最初のデータベースクエリを最適化するにはどうすればよいですか?
<?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に焦点を当てます。同意する場合は、https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simpleを参照してください。 -sql-query – Strawberry
2つのクエリ、特にループ内のクエリを実行しないのが理想的です。 –
私はスピードの問題がサブクエリとLEFT JOINに相対的だと思います。私はそれがあなたのサブクエリを削除し、通常の他のテーブルをジョインし、アポイントID(もしあれば)によってグループを使用し、最新のアポイントメントを取得するためにMAXを使用してクエリをスピードアップするためにINNER JOINを使用する方が良いと思います。 – Lucarnosky