2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【MySql】SELECT文が遅い時に試したこと【初心者向け】

2
Posted at

はじめに

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 では一緒に働くメンバーを募集しております。
詳しくは採用情報ページをご確認ください。

AppTime 採用情報

みなさまからのご応募をお待ちしております。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?