同じSQL文で極端に検索が遅くなる時がある

このQ&Aのポイント
  • とあるSQL文を実行すると、1秒で結果が返ってくる時と、20秒近く結果が返ってこない時があり、原因が何なのか分からず質問させていただきました。
  • 40万件と30万件レコードが存在する2つのテーブルを結合し、結果を表示しているプログラムがあります。この実行結果で、1秒で結果が返ってくる時と、20秒近く結果が返ってこない時があります。20秒近く結果が返ってこなくなる時間はだいたい30分くらいです。30分過ぎると、1秒で結果が返ってくるようになります。20秒近く結果が返ってこない時間帯になると、他のプログラムのSQL文にタイムアウトが発生します。
  • 基本的には1秒で結果が返ってきていますので、INDEXは正しく設定されていると思います。同じ条件のSQL文で処理時間が違う原因として、考えられることはございますでしょうか?
回答を見る
  • ベストアンサー

同じSQL文で極端に検索が遅くなる時がある

[環境] OS:CentOS    ⇒メモリ:4G    ⇒CPU:2コア(種類はわかりませんでした) DB:MySQL5.1.52 クライアント:Flex サーバー:php, Apache お世話になっております。 とあるSQL文を実行すると、1秒で結果が返ってくる時と、 20秒近く結果が返ってこない時があり、 原因が何なのか分からず質問させていただきました。 =以下詳細= 40万件と30万件レコードが存在する2つのテーブルを結合し、 結果を表示しているプログラムがあります。 この実行結果で、1秒で結果が返ってくる時と、 20秒近く結果が返ってこない時があります。  ※全く同じ条件で検索しています。  ※急にデータ量が増えたのではありません。 20秒近く結果が返ってこなくなる時間はだいたい30分くらいです。 30分過ぎると、1秒で結果が返ってくるようになります。 20秒近く結果が返ってこない時間帯になると、 他のプログラムのSQL文にタイムアウトが発生します。 基本的には1秒で結果が返ってきていますので、INDEXは正しく設定されていると思います。 同じ条件のSQL文で処理時間が違う原因として、考えられることはございますでしょうか? どなたかお分かりになる方いらっしゃいましたら、 ご教示いただければと思います。 よろしくお願い致します。

  • ctske
  • お礼率81% (44/54)
  • MySQL
  • 回答数4
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • nora1962
  • ベストアンサー率60% (431/717)
回答No.4

MySQLはQuery Cacheを持っているのでテーブルの更新がない場合、同じクエリがリクエストされた場合は高速に結果を返すことができます。しかし、テーブルの更新があるとキャッシュが効かなくなります。 また、SQLの書き方によってはバッファキャッシュの競合が発生し遅延することも考えられます。 速い時間帯と遅い時間帯で show processlist; で接続数を確認してください。 また、CPUやI/Oの待ちを調べるためにはsarやiostatを用います。 http://www.uetyi.mydns.jp/wordpress/linux-server/entry-992.html

ctske
質問者

お礼

ご回答ありがとうございます。 今回の問題なのですが、調査するだけの 時間がなかったということもあり、 SQL及びテーブル構成の修正という対応を とることになりました。 せっかくご回答くださってもらって申し訳ないのですが、 これにてクローズとさせていただきます。 他ご回答くださった方々もありがとうございました。 次回こういった問題が発生した際には、参考にさせていただきたいと思います。

その他の回答 (3)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

なんとも言えませんがキャッシュの問題じゃないですか? explainで有効なインデックスが設定されているか確認しながら チューニングするしかないと思いますよ

ctske
質問者

お礼

ご回答ありがとうございます。 インデックスを見直してみます。 また何かわかりましたら、追記いたします。

  • DIooggooID
  • ベストアンサー率27% (1730/6405)
回答No.2

DBサーバ上で処理されている、DBMS以外の処理内容(負荷状況)が気になります。 DBサーバ資源の負荷(cpuや、I/O[Disk]等)は、処理時間が短い時、長い時とで どのようになっていますか?

ctske
質問者

お礼

ご回答頂きまして、ありがとうございます。 今まさに遅い時間帯で、MySQL以外にタスクは動いていません。 CPUですが、SQL実行時にmysqldのCPU使用率が100%になります。 このSQLが実行し終わると、全体のCPU使用率も1%前後まで下がります。 全体のメモリ使用率は また、現時点でのmysqldのメモリ使用量はおよそ28%程のままで、 上下しておりません。 ↓実際のtopコマンドで取得した内容 top - 16:30:56 up 12:52, 2 users, load average: 0.09, 0.12, 0.08 Tasks: 75 total, 1 running, 74 sleeping, 0 stopped, 0 zombie Cpu(s): 0.2%us, 0.2%sy, 0.0%ni, 99.5%id, 0.0%wa, 0.0%hi, 0.2%si, 0.0%st Mem: 4044540k total, 3299440k used, 745100k free, 190332k buffers Swap: 4095992k total, 0k used, 4095992k free, 1818508k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ OMMAND 2963 mysql 15 0 1921m 1.1g 5656 S 3.0 28.6 25:14.87 mysqld I/Oに関してましては、ちょっと確認方法がわからなかったため 現在調査中です。 よろしくお願い致します。

ctske
質問者

補足

すみません。訂正です。 お礼欄の >全体のメモリ使用率は >また、現時点でのmysqldのメモリ使用量はおよそ28%程のままで、 >上下しておりません。 の箇所の、書きかけのところですが、 >全体のメモリ使用量は、4G中およそ3Gになります。 >また、現時点でのmysqldのメモリ使用量はおよそ28%程のままで、 >上下しておりません。 です。

  • chie65535
  • ベストアンサー率43% (8516/19358)
回答No.1

クエリの結果を、バックグラウンドで30分かけて、中間ファイルに作っているのでは? 一旦、中間ファイルが出来てしまえばそれを使うので1秒で結果が返って来るけど、中間ファイルが出来る前にやると中間ファイルを利用出来ないので20秒かかる、と考えれば、つじつまが合います。

ctske
質問者

お礼

ご回答頂きまして、ありがとうございます。 大変申し訳ないのですが、「中間ファイル」とは どういったものを差すのでしょうか。 キャッシュやテンポラリとは違うものなのでしょうか。 調べ方が悪いのかもしれませんが、それらしきサイトにたどり着きませんでした・・・。 お手数ですがよろしくお願い致します。

関連するQ&A

  • “SQL文を作るSQL”の書き方ってありますか?

    “SQL文を作るSQL”の書き方ってあるのでしょうか? 例えばなのですが、表同士を大量に結合して条件に当てはまったものをアップデートするようなSQLを書く場合、文法を間違うとエライこちゃ!になる場合がありますよね。 そういう場合って結合するんじゃなくて結合したSELECT文を使って条件だしをして1件1件単純アップデートをした方が安心ですよね。 (定期処理であれば効率が悪いですが・・・だったらプロシージャですか・・・というところになりますがごくたまにや1回きりのデータ変更など) そういったことをやるほうほうはありますでしょうか? 仕様はSQL99です。

  • 同じSQL文で速度がだいぶ違う

    10万件程度レコードをもつ2つのテーブルに対し、下記のようなSQL文を実行します。 (実際のSQL文とは違いますが、だいたいこんな感じです。) SELECT * FROM aaa JOIN bbb USING(key) WHERE ORDER BY ccc LIMIT 50 OFFSET 5000 すると、 CGIから実行→CPU使用率が一時的に60%を超える。1~2秒待たされる。 phpMyAdminから同じSQL文を実行→CPUほどんど消費せず。瞬時に終わる。 のようにCGIからとphpMyAdminからで速度に大きな違いがあります。 こんなに差が付いてしまう理由がわかりましたら教えていただきたく。

    • ベストアンサー
    • MySQL
  • SQL文長の制限

    PostgreSQL8.1.3にて、長いwhere句のあるSELECT文を実行したところ、 「server closed the connection unexpectedly」 のエラーとなってしまいました。 エラーとなったSQL文は317726文字で、 where句のin条件のリスト個数が非常に多くなっています。 試しに、in条件のリスト部分を減らし、 156000文字までSQL文を短く短くしたら、エラーは回避できました。 in条件ではなくor条件に変更すると、エラーとの境目のSQL文長は上記とは異なることから、 SQL文長だけが影響しているとは思えません。 SQL文を改修して、エラーを回避するにしても、ここらへんの限界値がわからないと改修できませんので、 改修の目安(信頼できるSQL文長がどのくらいなのかなど)をご教授お願いします。

  • ACCESSのクエリで同じSQL文だが結果が異なる

    ACCESS2003にて 選択クエリAをSQLビューで開きSQL文をコピー、 新規作成したクエリBのSQLビューに貼り付けて実行したところ、 AとBで結果の件数が異なりました。 そのままBを保存して終了。 BをSQLビューで開き、 SQL文の末尾の;を削除して実行すると、 Aと同じ件数の結果になりました。 再度Bを保存して終了し、 BをSQLビューで開き、 SQL文の末尾の;を削除して実行すると、 Aと異なる件数(元の結果)になりました。 何が原因なのでしょうか。 SQL文の内容は、サブクエリを含んでいて、サブクエリのFROMは SQLSERVERのリンクテーブルです。 よろしくお願いします。

  • SQL文で複数の項目のうちひとつの項目のみの重複を排除する方法を教えてください。

    以下のデータ1(5件)に対してSQL文でSELECTを実行して結果(2件)が返ってくるようなSQL文はありませんでしょうか? 条件は県名の重複を排除して年月日の最新のもののみを持ってくるというものです。 【データ1】 (県名 年月日     金額) 埼玉  20090401 100 埼玉  20090402 100 埼玉  20090403 100 東京  20090501 100 東京  20090502 100 【結果】 (県名 年月日     金額) 埼玉 20090403 100 東京 20090502 100 DISTINCTや副問い合わせを考えたのですがうまいやり方が見つかりませんでした。 また、VBなどは使用せずSQL文のみを使用したいです。 お手数ですがよろしくお願いします。

  • 日付を表示形式で戻すSQL文を書きたい

    2つの日付を与えてその2つの日付の間の日付を以下のような表形式で返すSQL文を作りたい。 可能でしょうか? 例えば、与える日付を以下の2つとして、 2012/01/05,2012/01/11 SQL文の実行結果は、 カラム名 2012/01/05 2012/01/06 2012/01/07 2012/01/08 2012/01/09 2012/01/10 2012/01/11 今回の例では、2012/01/05~2012/01/11までの7日間なので7件が返された。

  • 同じSQL文での検索結果が異なる

    visualbasic2005とoracleを使ってデータベース管理ソフトを作っています。 ひとつのデータのフィールドはいくつかあるのですが、 DATAUPLOADというフィールド値をSQL文で検索するときのみ、 土曜日のデータを拾おうとするとなぜか検索をかけるごとに 件数が1件ずつ減っていくという現象が起きています。 他のフィールドや土曜日以外のフィールドの検索の時には そのようなエラーは起こらないのですが、 同じSQL文で検索結果が随時異なってしまう場合には どのような原因が考えられますでしょうか? DATAUPLOAD は'2008/03/12 00:00:00'の形式のDate型データです。 あるDATE(日付)のデータを検索するときに使用しているSQL文は、 SELECT * FROM DATABASE WHERE DATEUPLOAD BETWEEN TO_DATE(' & CStr(Format(DATE, "yyyy/MM/dd")) & 00:00:00','yyyy/MM/dd hh24:mi:ss') AND TO_DATE(' CStr(Format(DATE, "yyyy/MM/dd")) & 23:59:59','yyyy/MM/dd hh24:mi:ss') です。 いろいろとSQL文を変更してみたのですが、 同じエラーが続いています。 何か思い当たることがありましたら 教えていただければと思います。

  • (2)-SQL文の書き方を教えてください。

    table項目:名称、日付、数量。 以上のtabelから以下のクエリーをつくりたいです: クエリー項目:名称、当日数量、当月数量。 日付の値は、フォーム上で指定する。 具体的に:フォーム上日付欄に2003/10/01と2003/10/30を指定し、実行すると、当日数量は、2003/10/30その日の合計数が出る。当月数量に指定された10/01から10/30までの数字の合計がでる。 今、片方だけ条件のSQL文を書けるですが、二つ条件のSQL文がとても難しい。 そうゆうSQL文を教えていただけませんか? よろしくお願いいたします。

  • Oracle SQL実行時間について

    Oracle初心者です。 あるテーブル(レコード数:100万件程度)に対してSelectするSQLの実行時間を、Oracleのset timing on, set autotrace onlyで計測しました。 結果は1000ms程度だったのですが、 同じSQL文を実行するプログラム(java)を作成し、pstmt.executequery()してresultsetからデータをgetするまでの時間をログに出力させたところ、400ms程度でした。 プログラムの性能目標として、set timing on の値を設定していたため、実際の結果(javaプログラムが出力した処理時間)の評価に困っています。 差がでる原因をご教示いただけませんでしょうか。 宜しくお願いします。

  • SQL文について

    こんにちは! 皆様に教えて欲しいことがあります。 DBの中のデータで、一番年齢が高い人の名前を取得してくるときってどんなSQL文を書けばいいんでしょうか? 一番高い年齢を取得、なら select Max(年齢) from DB でいいと思うんですけど、一番年齢の高い人の名前、となると、どうやってとってくるのかわかりません。 where文で「having max(年齢)」ってやったんですけど、エラーが出て実行できませんでした。 今作ってるSQL文は、DB二つから他の条件も含めてselectしているので、他の理由でエラーになってるのかもしれませんが・・・。 職場にSQLがわかる人がいないので、誰にも聞けません。 もしわかる方がいらっしゃいましたら、教えてください。 宜しくお願いします。