我们正在运行的网络应用使用的其中一个查询如下:
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等等,但我没有到达任何地方。
我很欣赏有关如何优化查询的一些建议。感谢。
编辑:唉!我没有关于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:
patients_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索引并按@DRapp的建议再次尝试STRAIGHT_JOIN:
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 |
+----+-------------+-------+--------+-------------------+-----------+---------+-------------------+------+----------------------------------------------+
所以我认为看起来好多了,但我不确定该怎么说。此外,查询似乎仍然需要与以前相同的时间。
答案 0 :(得分:1)
我会使用STRAIGHT_JOIN并使用第一个包含patients_reports表的查询,然后继续加入患者表中以获取其姓名信息。另外,如果我没有看到它,那么PATIENT_ID列中的patients_reports表是否有一个索引,或者作为复合索引键的第一个元素?
此外,确保RESULTS在Report_ID上有索引,与TEST_RESULTS(Result_ID索引)相同
答案 1 :(得分:0)
results.report_id索引了吗?它没有找到一个键并且正在进行表扫描。我假设results.id实际上是主键。
另外,如果它的report_id是主键,而且它是INNODB,它应该聚集在该索引上,所以绝对不知道为什么如果 以这种方式配置的话,它不会快速尖叫。