Один из запросов, используемых веб-приложением, которое мы выполняем, выглядит следующим образом:
SELECT
p.id, r.id AS report_id, tr.result_id,
r.report_date, r.department, r.reportStatus, rs.specimen,
tr.name, tr.value, tr.flag, tr.unit, tr.reference_range
FROM patients AS p
INNER JOIN
patients_reports AS pr ON pr.patient_id = p.id
INNER JOIN
reports AS r ON pr.report_id = r.id
INNER JOIN
results AS rs ON r.id = rs.report_id
INNER JOIN
test_results AS tr ON rs.id = tr.result_id
WHERE pr.patient_id = 17548
ORDER BY rs.specimen, tr.name, r.report_date;
План объяснения выглядит следующим образом:
+----+-------------+-------+--------+---------------+-----------+---------+-------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+-----------+---------+-------------------+--------+----------------------------------------------+
| 1 | SIMPLE | p | const | PRIMARY | PRIMARY | 4 | const | 1 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | rs | ALL | PRIMARY | NULL | NULL | NULL | 152817 | |
| 1 | SIMPLE | r | eq_ref | PRIMARY | PRIMARY | 4 | demo.rs.report_id | 1 | |
| 1 | SIMPLE | pr | eq_ref | PRIMARY | PRIMARY | 8 | const,demo.r.id | 1 | Using where; Using index |
| 1 | SIMPLE | tr | ref | result_id | result_id | 5 | demo.rs.id | 1 | Using where |
+----+-------------+-------+--------+---------------+-----------+---------+-------------------+--------+----------------------------------------------+
Запрос возвращает 27371 строк,В настоящий момент в test_results находится 152730 строк.Это всего лишь небольшой объем демонстрационных данных.
Я пытался повысить эффективность запроса, но у меня возникли проблемы с его быстрым выполнением.Я просмотрел различные статьи по документации и вопросы по stackoverflow, но не смог это исправить.
Я попытался удалить одно из соединений следующим образом:
SELECT
pr.patient_id, r.id AS report_id, tr.result_id,
r.report_date, r.department, r.reportStatus, rs.specimen,
tr.name, tr.value, tr.flag, tr.unit, tr.reference_range
FROM patients_reports AS pr
INNER JOIN
reports AS r ON pr.report_id = r.id
INNER JOIN
results AS rs ON r.id = rs.report_id
INNER JOIN
test_results AS tr ON rs.id = tr.result_id
WHERE pr.patient_id = 17548
ORDER BY rs.specimen, tr.name, r.report_date;
Тогда план запроса выглядит следующим образом:
+----+-------------+-------+--------+---------------+-----------+---------+-------------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+-----------+---------+-------------------+--------+---------------------------------+
| 1 | SIMPLE | rs | ALL | PRIMARY | NULL | NULL | NULL | 152817 | Using temporary; Using filesort |
| 1 | SIMPLE | r | eq_ref | PRIMARY | PRIMARY | 4 | demo.rs.report_id | 1 | |
| 1 | SIMPLE | pr | eq_ref | PRIMARY | PRIMARY | 8 | const,demo.r.id | 1 | Using where; Using index |
| 1 | SIMPLE | tr | ref | result_id | result_id | 5 | demo.rs.id | 1 | Using where |
+----+-------------+-------+--------+---------------+-----------+---------+-------------------+--------+---------------------------------+
Так что не сильно отличается.
Я попытался изменить порядок запроса и использовать STRAIGHT_JOIN среди других вещей, но я никуда не попал.
Буду признателен за некоторые рекомендации по оптимизации запроса.Спасибо.
РЕДАКТИРОВАТЬ: Argh!У меня не было индекса для results.report_id, но, похоже, он не помог:
+----+-------------+-------+--------+-------------------+-----------+---------+-------------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------+-----------+---------+-------------------+--------+---------------------------------+
| 1 | SIMPLE | rs | ALL | PRIMARY,report_id | NULL | NULL | NULL | 152817 | Using temporary; Using filesort |
| 1 | SIMPLE | r | eq_ref | PRIMARY | PRIMARY | 4 | demo.rs.report_id | 1 | |
| 1 | SIMPLE | pr | eq_ref | PRIMARY | PRIMARY | 8 | const,demo.r.id | 1 | Using where; Using index |
| 1 | SIMPLE | tr | ref | result_id | result_id | 5 | demo.rs.id | 1 | Using where |
+----+-------------+-------+--------+-------------------+-----------+---------+-------------------+--------+---------------------------------+
EDIT2:
Patient_reports выглядит следующим образом:
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| patient_id | int(11) | NO | PRI | 0 | |
| report_id | int(11) | NO | PRI | 0 | |
+------------+---------+------+-----+---------+-------+
EDIT3:
После добавления индекса results.report_id и повторной попытки STRAIGHT_JOIN в соответствии с предложением @DRapp:
SELECT STRAIGHT_JOIN
r.id AS report_id, tr.result_id,
r.report_date, r.department, r.reportStatus, rs.specimen,
tr.name, tr.value, tr.flag, tr.unit, tr.reference_range
FROM patients_reports AS pr
INNER JOIN
reports AS r ON pr.report_id = r.id
INNER JOIN
results AS rs ON r.id = rs.report_id
INNER JOIN
test_results AS tr ON rs.id = tr.result_id
WHERE pr.patient_id = 17548
ORDER BY rs.specimen, tr.name, r.report_date;
план выглядит следующим образом:
+----+-------------+-------+--------+-------------------+-----------+---------+-------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------+-----------+---------+-------------------+------+----------------------------------------------+
| 1 | SIMPLE | pr | ref | PRIMARY | PRIMARY | 4 | const | 3646 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | r | eq_ref | PRIMARY | PRIMARY | 4 | demo.pr.report_id | 1 | |
| 1 | SIMPLE | rs | ref | PRIMARY,report_id | report_id | 5 | demo.r.id | 764 | Using where |
| 1 | SIMPLE | tr | ref | result_id | result_id | 5 | demo.rs.id | 1 | Using where |
+----+-------------+-------+--------+-------------------+-----------+---------+-------------------+------+----------------------------------------------+
Так что я думаю, что это выглядит намного лучше, но я не уверен, как именно сказать.Кроме того, запрос все еще занимает примерно столько же времени, что и раньше.