どもです。
MySQL初心者、やらかしました。
開発では問題なかったのに、テストアップしたらこんな感じのエラーに遭遇しまして。
このエラーについて調べてみると、
・DBが壊れている
・tmp領域に空きが無い
この2件が出てきたのですが、原因はもっと間抜けなものだったという戒めの備忘録です。
やりたかったのは、こんな感じ。
親
+-------+------------------------+
| ID | 条件Aに一致する子番号 |
+-------+------------------------+
| 1 | 2 |
| 2 | 1 |
| 3 | 3 |
| 4 | 2 |
+-------+------------------------+
子
+-------+-------+--------+
| 親ID | 枝番 | セット |
+-------+-------+--------+
| 1 | 1 | 1 |
| 1 | 2 | 2 |
+-------+-------+--------+
| 2 | 1 | 1 |
| 2 | 2 | 1 |
+-------+-------+--------+
| 3 | 1 | 1 |
| 3 | 2 | 1 |
| 3 | 3 | 2 |
+-------+-------+--------+
| 4 | 1 | 1 |
| 4 | 2 | 2 |
| 4 | 1 | 3 |
+-------+-------+--------+
1つの親に対して複数の子があるテーブルで、
親の方に「特定の条件に合致する一つの子の枝番」を記録しています。
で、子のデータを取得するときに、
自分が「特定の条件に合致する枝番が含まれたセットかどうか」を判断したい。
ので、
①子から親に「ID」でJOIN。
②JOINした親から子に「条件Aに一致する子番号」と「枝番」でJOIN。
③JOINした、「条件Aに一致する子番号の子」データから、セット番号を取得。
としました。
で、このFROM部が、こうなるわけです。
FROM 子
LEFT JOIN 親 ON 子.親ID = 親.ID
LEFT JOIN 子 AS 子α ON 親.条件Aに一致する子番号 = 子α.枝番
うん、日本語で書くと何がおかしいか、一目でわかるものですね。
こらあかんわ。
この記述だと上記テーブルの場合、[親ID-枝番]として、
[1-1]に対して枝番=2の分、つまり[1-2][2-2][3-2][4-2]の4件がHitしてしまい、
その結果、[1-1]が4行できてしまいます。
開発環境はデータ数が少ないのでこの程度ですが、これが仮に1万件のデータが入っていた場合…
単純計算で子1件につき1万件の行が作成されるわけで…
そりゃ、処理落ちしますな! 当然ですな!
見たことのないエラーだったので原因がピンと来なく、原因特定が遅れてしまいました。
Incorrect key file for table は処理落ちでも発生しうる。僕、覚えた。
ちなみに本件の正解FROMは、こう。
FROM 子
LEFT JOIN 親 ON 子.親ID = 親.ID
LEFT JOIN 子 AS 子α ON 親.条件Aに一致する子番号 = 子α.枝番 AND 親.ID = 子α.親ID
JOINでANDを使うの、つい忘れるんだよなぁ。気をつけねば。