はじめに
Mysqlのselect文が遅い時の対処法を記載します。
ただ、「EXPLAINでtypeがフルスキャンになっていないか確認」とか、「indexがはられているか見ろ」など、そんなのは調べればいくらでも出てきます。
そこで、私が対応した中で、「速くなったなあ~」と実感できたやり方をいくつかご紹介します。
参考になれば幸いです。
WHERE句を追加
以下のようなselect文があるとします。
select *
from testtable1 as test1
inner join testtable2 as test2 on test2.test1_id = test1.id
inner join testtable3 as test3 on test3.test1_id = test1.id
where IFNULL(test2.flag, 0) = 0
EXPLAINでtypeを確認すると、testtable1がALL(フルスキャン)となっている、もしくは「rows」の数値が多い場合
where test1.id != 0 を追加すると、typeがrange(indexを用いた範囲検索)となり、速度が改善する可能性があります。
select *
from testtable1 as test1
inner join testtable2 as test2 on test2.test1_id = test1.id
inner join testtable3 as test3 on test3.test1_id = test1.id
where test1.id != 0
and IFNULL(test2.flag, 0) = 0
indexを指定
以下のようなselect文があるとします。
select *
from testtable1 as test1
inner join testtable2 as test2 on test2.test1_id = test1.id
inner join testtable3 as test3 on test3.test1_id = test1.id
where test1.date_from >= '2025/12/01'
and test1.date_to <= '2025/12/31'
同じく、testtable1が原因で遅くなっている場合、「USE INDEX」で特定のインデックスの使用を提案すると、改善される可能性があります。
下記の場合だと、date_fromのindexを使用してくださいと提案しています。
select *
from testtable1 as test1 USE INDEX(testtable1_date_from_index)
inner join testtable2 as test2 on test2.test1_id = test1.id
inner join testtable3 as test3 on test3.test1_id = test1.id
where test2.date_from >= '2025/12/01'
and test2.date_to <= '2025/12/31'
「show index from testtable1」でKey_nameを確認し、それを指定してください。
joinが原因かも
以下のようなselect文があるとします。
select *
from testtable1 as test1
inner join testtable2 as test2 on test2.test1_id = test1.id
inner join testtable3 as test3 on test3.test1_id = test1.id
inner join testtable4 as test4 on test4.test1_id = test1.id
inner join testtable5 as test5 on test5.test1_id = test1.id
inner join testtable6 as test6 on test6.test1_id = test1.id
where test2.date_from >= '2025/12/01'
and test2.date_to <= '2025/12/31'
上記2つの内容を実施しても速度が改善しなかった場合、どれかのjoinが影響している可能性があります。
やり方はシンプルで、joinしているテーブルを1つ消してselectを実行、速度に変化が無い場合は、もう1つ消して実行…を繰り返します。
例えば、
「inner join testtable6 as test6 on test6.test1_id = test1.id」を消して、selectしても変化は無かった、
「inner join testtable5 as test5 on test5.test1_id = test1.id」を消して、selectしたら速度が改善された場合、そのjoinが何かしら影響していると考えられます。
私の場合、indexがはられていなかったことが原因でした。
joinでORを使用している
以下のようなselect文があるとします。
select *
from testtable1 as test1
inner join testtable2 as test2 on test2.test1_id = test1.id or test2.old_test1_id = test1.id
inner join testtable3 as test3 on test3.test1_id = test1.id
where test2.date_from >= '2025/12/01'
and test2.date_to <= '2025/12/31'
OR条件はインデックスが効かなくなり、両方の列をスキャンしながら比較するためパフォーマンスが落ちます。
test2.test1_idと、test2.old_test1_idをUNION ALL に分割することで、改善することがあります。
(
select test1.id, test2.id, test2.old_test1_id
from testtable1 as test1
inner join testtable2 as test2 on test2.test1_id = test1.id
inner join testtable3 as test3 on test3.test1_id = test1.id
where test2.date_from >= '2025/12/01'
and test2.date_to <= '2025/12/31'
)
UNION ALL
(
select test1.id, test2.id, test2.old_test1_id
from testtable1 as test1
inner join testtable2 as test2 on test2.old_test1_id = test1.id
inner join testtable3 as test3 on test3.test1_id = test1.id
where test2.date_from >= '2025/12/01'
and test2.date_to <= '2025/12/31'
)
ORを使用されている方はぜひお試しください。
お知らせ(採用情報)
最後にお知らせとなりますが、AppTime では一緒に働くメンバーを募集しております。
詳しくは採用情報ページをご確認ください。
みなさまからのご応募をお待ちしております。