質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.21%

データベースのパフォーマンスで疑うべき3つのポイント

解決済

回答 4

投稿

  • 評価
  • クリップ 3
  • VIEW 2,571

ayu

score 202

こんばんわ。

データベースのパフォーマンスについて、質問したいことがあります。

  • データベースのパフォーマンスが悪い理由
  • n + 1問題
  • index問題

この3つ以外にあると思うので、もしあればなぜ、それを見直すべき必要があるのかの理由も書いてほしいです。

自分の理由です。

 データベースのパフォーマンスが悪い理由

コンピュータはメモリー上のデータの出し入れは早いが、HDDへのアクセスは遅い
データベースはHDDへのアクセスを行っているので、基本的にパフォーマンスは遅くなる。
もし、メモリー上にデータベースを展開できるのなら、高速アクセスは可能になる
→redis, memcached
Mysqlもクエリをメモリー上にキャッシュをするが、全てできるわけではない

 n + 1問題

ループで回す処理を毎回クエリを作成しているので遅くなる。
クエリを工夫するだけで一回で取得できる。
このことから、n + 1問題に限らず、余計なクエリを作成しているところを直すことが必要。

 index問題

HDDにアクセスする際に、indexがないとレコード全てから探すことになる。
indexを貼ってあれば、余計なレコードから探さなくて良くなる

 まとめ

  • データベースのパフォーマンスが悪い理由
    →コンピュータの性質の問題
  • n + 1問題
    →クエリの問題
  • index問題
    →DBアクセスの検索ロジックの問題

まとめると上記の中身だと思っています。
これ以外に注意点や、考えが間違っていることがあれば、教えていただきたいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2017/06/04 22:21

    質問をもう一度読み直してみてください。

    キャンセル

  • ayu

    2017/06/05 21:19

    あまり質問になっていなかったですね。申し訳ございませんでした。

    キャンセル

回答 4

checkベストアンサー

+4

クエリの実行計画も重要な問題となります。とりわけ、複数のテーブルを組み合わせるような複雑なSQLを組み立てる場合、SQLの実行エンジンが不適切な実行法を選択してしまえば、無駄に時間がかかってしまいます。

幸い、実行計画を調べる方法もありますので、遅いクエリに対しては確認を行ってみましょう。

MySQLのEXPLAINを徹底解説!!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/05 21:27

    確かに・・・。

    EXPLAINで原因を調べるのは、基本ですね。

    基本が抜けてましたm(_ _)m

    ありがとうございます!

    キャンセル

+2

システム規模やテーブル数、レコード数など、
いろいろな要因があるので、
「パフォーマンスに悪影響も及ぼすのは、これ」という回答はありません。

質問で言われている3つのポイントで、
間違っていることはありませんが、問題を解決してもパフォーマンスが必ず向上するわけではありません。

例えば、
一番多いレコードが5万レコードを下回るようなテーブルしかない小規模のシステムであれば、
おそらくどれも問題になりません。
(少々の速度向上には繋がるかもしれませんが、有意義なものではないと判断されることのほうが多い)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/05 21:24

    >一番多いレコードが5万レコードを下回るようなテーブルしかない小規模のシステムであれば、
    おそらくどれも問題になりません。

    なんと!

    それ以上じゃないと、そこまで効果ないんですね。

    無意味にでかいサイトをイメージして頑張ります。

    キャンセル

+1

MySQLで言うと、相関サブクエリが劇的に遅いというのが有名ですね。
相関サブクエリとは、サブクエリ内で外部のクエリ結果を参照しているものです。
ようは、サブクエリ単体では実行できないやつですね。(他に依存しているため)
ちょっといい例が浮かばいのですが、例えば以下のようなやつです。

SELECT
  * 
FROM
  FOO A 
WHERE
  A.CODE IN ( 
    SELECT
      B.CODE 
    FROM
      BAR B 
    WHERE
      A.CODE = B.CODE /* ここでAを参照している */
  ); 

これは以下のように書き換えれば問題なくなります。

SELECT
  * 
FROM
  FOO A 
  INNER JOIN BAR B 
    ON A.CODE = B.CODE; 

相関サブクエリは実行計画では、DEPENDENT SUBQUERYとなるので、
そこは確実にチューニングポイントになります。

ただし、MySQL5.6からはオプティマイザが賢くなっているようで、
相関サブクエリでも、DEPENDENT SUBQUERYにはならないようになっているようです。
つまり速くなったということです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/05 10:05

    すみません。すでに書かれている
    >余計なクエリを作成しているところを直すことが必要。
    に該当しますね。流してください。

    キャンセル

  • 2017/06/05 21:26

    相関サブクエリについて、丁寧な解説ありがとうございます!

    仕組みが分かっていなかったので、大変助かりましたm(_ _)m

    ありがとうございます!

    キャンセル

+1

場合によってはインデックスを使わずフルスキャンしたほうが早い場合さえあります。
インデックススキャンするということは、インデックスによってレコードを決定できる、ということでしかありません。
その後にレコードを読むことになった場合、シーケンシャルに一気に読めるフルスキャンより、ランダムアクセスになって遅くなる可能性があるのです。
※インデックスによる絞り込みが十分ではなく、また SELECT 対象がインデックスの構成要素以外にもある場合が該当する

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/05 21:20

    インデックスが常に最適なわけではないのですね。

    > SELECT 対象がインデックスの構成要素以外にもある場合が該当する

    なるほど!

    ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる