場合によっては、LoopBack はリレーショナル データベースを非常に非効率的に処理しているように見えます。パフォーマンスの問題に遭遇しました。誰かがそれを回避する方法を見つけたのではないかと思っていました。
これを実証するために、以下に示すように、3 つのテーブルと単純な多対多の関係を持つ MySQL データベースを作成しました。
これは非常に標準的で一般的な状況です (ちなみに、LoopBack のドキュメントから直接借用しました)。
テーブルにデータを入力した方法は次のとおりです。
mysql> SELECT * FROM physician;
+----+----------+
| id | name |
+----+----------+
| 1 | Smith |
| 2 | Johnson |
| 3 | Williams |
| 4 | Jones |
+----+----------+
mysql> SELECT * FROM patient;
+----+----------+
| id | name |
+----+----------+
| 1 | Anderson |
| 2 | Jackson |
| 3 | White |
| 4 | Roberts |
| 5 | Lewis |
| 6 | Clark |
| 7 | Morgan |
+----+----------+
mysql> SELECT * FROM appointment;
+----+--------------+------------+------------+
| id | physician_id | patient_id | date |
+----+--------------+------------+------------+
| 6 | 1 | 1 | 2014-06-12 |
| 7 | 1 | 3 | 2014-06-12 |
| 8 | 1 | 5 | 2014-06-12 |
| 9 | 2 | 2 | 2014-06-12 |
| 10 | 2 | 4 | 2014-06-12 |
| 11 | 3 | 7 | 2014-06-12 |
| 12 | 2 | 2 | 2014-06-13 |
+----+--------------+------------+------------+
physician_id = 2
ここで、Dr. Johnson ( )との予約がある患者のリストを見つけたいとしましょう。これを実現するには、次のような賢明な方法がいくつかあります。
SELECT * FROM patient WHERE id IN( SELECT patient_id FROM appointment WHERE physician_id = 2 )
また
SELECT patient.* FROM patient JOIN appointment ON patient.id = appointment.patient_id WHERE appointment.physician_id = 2
LoopBack がバックグラウンドで行うことは、まったく別の話です。
SELECT `id`, `physician_id`, `patient_id`, `date` FROM `appointment` WHERE `physician_id` = 2 ORDER BY `id`
SELECT * FROM `patient` WHERE `id` = 2 LIMIT 1
SELECT * FROM `patient` WHERE `id` = 4 LIMIT 1
SELECT * FROM `patient` WHERE `id` = 2 LIMIT 1
ここでわかることは、最初に Johnson 医師のすべての予約を検索し (最初のクエリ)、次にpatient
前のクエリ (最後の 3 つのクエリ) で見つかった患者 ID のテーブルを検索することです。結果は次のとおりです。
[
{
"id": 2,
"name": "Jackson"
},
{
"id": 4,
"name": "Roberts"
},
{
"id": 2,
"name": "Jackson"
}
]
これは非常に非効率に見えます。上記の 4 つの SQL クエリを見ることができます。これは事実上の1 + n
クエリですn
。つまり、LoopBack はpatient
、最初のクエリで見つかった患者の数だけ MySQL にテーブルをスキャンさせます。患者テーブル内のレコード数が増えると、明らかにこれは非常に非効率的になります。
これをより効率的に達成できる他の方法はありますか?