データベースの速度差の理由とは?

このQ&Aのポイント
  • データベースの構造とインデックス、検索クエリーを同じ条件でテストサーバと実際のサーバで比較した結果、10倍までの速度差が生まれました。
  • 違う箇所としては、実際のサーバのCPU:Xeon 3.2GHz メモリ:2GB、テストサーバのCPU:Pentium4 3.2GHz メモリ:2GBとなっています。
  • スペックの違いやデータベースの最適化の有無などが速度差の原因と考えられます。
回答を見る
  • ベストアンサー

速度差の理由を教えてください。

データベースの構造とインデックス、検索クエリー 全て同じ条件でテストサーバと実際のサーバで 検索を行っているのですが以下のような結果がでます。 なぜ以下の様に10倍まで差が生まれるのかを 教えていただければと思っております。 違う箇所としては、サーバのスペックですが 実際のサーバのCPU:Xeon 3.2GHz メモリ:2GB テストサーバのCPU:Pentium4 3.2GHz メモリ:2GB となります。 //テストサーバでの結果 Limit (cost=99427.05..99427.25 rows=4 width=112) (actual time=4022.29..4022.31 rows=4 loops=1) -> Unique (cost=99427.05..99438.37 rows=226 width=112) (actual time=4022.29..4022.30 rows=5 loops=1) -> Sort (cost=99427.05..99432.71 rows=2265 width=112) (actual time=4022.29..4022.29 rows=6 loops=1) Sort Key: s.saorderid, s.saserialid, o.odlastupdate -> Merge Join (cost=96997.70..99300.85 rows=2265 width=112) (actual time=3363.93..4022.11 rows=40 loops=1) Merge Cond: ("outer".odid = "inner".saorderid) -> Sort (cost=8054.50..8059.58 rows=2033 width=68) (actual time=13.52..13.55 rows=38 loops=1) Sort Key: o.odid -> Index Scan using order1_odctmid_index on order1 o (cost=0.00..7942.81 rows=2033 width=68) (actual time=13.13..13.47 rows=38 loops=1) Index Cond: (odctmid = 3403::bigint) -> Sort (cost=88943.20..90075.54 rows=452935 width=44) (actual time=3344.05..3688.13 rows=452002 loops=1) Sort Key: s.saorderid -> Seq Scan on sale s (cost=0.00..12792.35 rows=452935 width=44) (actual time=0.02..756.03 rows=452935 loops=1) Total runtime: 4050.02 msec //実際の本番サーバでの結果 Limit (cost=73933.37..73933.39 rows=1 width=128) (actual time=43102.58..43102.59 rows=4 loops=1) -> Unique (cost=73933.37..73933.39 rows=1 width=128) (actual time=43102.58..43102.59 rows=5 loops=1) -> Sort (cost=73933.37..73933.38 rows=5 width=128) (actual time=43102.57..43102.58 rows=6 loops=1) Sort Key: s.saorderid, s.saserialid, o.odlastupdate -> Nested Loop (cost=0.00..73933.32 rows=5 width=128) (actual time=998.20..43102.38 rows=40 loops=1) Join Filter: ("outer".odid = "inner".saorderid) -> Index Scan using order1_odctmid_index on order1 o (cost=0.00..18.12 rows=4 width=68) (actual time=6.01..6.99 rows=38 loops=1) Index Cond: (odctmid = 3403::bigint) -> Seq Scan on sale s (cost=0.00..12797.54 rows=448254 width=60) (actual time=0.01..756.51 rows=455437 loops=38) Total runtime: 43102.69 msec もしクエリー文もあった方がよければ お知らせ下さい。 すみませんが、どなたか教えて頂ければ と思います。よろしくお願い致します。

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

  • ベストアンサー
回答No.3

URLを貼り忘れました。 http://www.postgresql.jp/ また、差が出ているポイントは、テスト環境ではMerge Join、本番環境ではNested Loop さらにloops=38となっている部分だと思います。 具体的に「SQLのどの記述の部分」ということは、インデクスの定義とSQLが分からないと具体的にはアドバイスできません。

unhork
質問者

お礼

遅れましたが 非常にありがたいアドバイスです。 テストと本番ですので、データ量の違いは埋めれない ないのですが、それでも数千程度の違いでなぜ10倍物 差が出るのか不思議でならなかったのですが、 教えていただいたポイントを頼りにもう少し調べて行きたいと 思います。 どうもありがとう御座います。

その他の回答 (2)

回答No.2

#1です。 PostgeSQLのバージョンが不明ですが、EXPLAINの表示結果の見方は、マニュアルの次のような箇所にあります。 http://www.postgresql.jp/document/pg800doc/html/performance-tips.html 私は「専門家」としていますが、PostgreSQLのこの辺の情報の解析、細かな性能に関するパラメタ類に関しては、それ程、詳しくありません。 また、PostgreSQLには、アクセス計画の生成に関するいろいろなパラメタがあるようで、このサイトでは適切に答えられる人はなかなかいません。 日本PostgreSQLユーザ会のメーリングリストに登録し、質問することをお勧めします。(私も登録していて、時々、アドバイスしています)

回答No.1

自分で解析しようと努力しましたか? ここのサイトは、「分からない部分を具体的示し、質問する」サイトであり、解析 作業を誰かにやってもらうサイトではありません。 >データベースの構造とインデックス、検索クエリー >全て同じ条件でテストサーバと実際のサーバで >検索を行っている データ件数や重複件数などが、全然違うのでは? ご自身で貼り付けた情報を見てみてください。 操作対象になっている行数が全然違うし、あちこちアクセス計画も違っています。

関連するQ&A

  • 前方一致が動的に変更される場合にINDEXは有効になりません。

    いつもお世話になっております。 テーブル同士のLIKE検索(前方一致)を行った場合、 INDEXが有効になりません。 LIKE検索文字列を固定にした場合は、INDEXが有効 になります。 テーブル同士のLIKE(前方一致)でINDEXを 有効にする手段をご教授頂けないでしょうか。 以下、実行結果です。 (1)LIKE検索文字列が固定 ---------------------------------------------------------------------------- EXPLAIN SELECT * FROM wk_dss_data WHERE sys_id LIKE 'M004964%'; ---------------------------------------------------------------------------- Index Scan using i_wk_dss_data_02 on wk_dss_data (cost=0.00..5.25 rows=1 width=311) Index Cond: (((sys_id)::text >= 'M004964'::character varying) AND ((sys_id)::text < 'M004965'::character varying)) Filter: ((sys_id)::text ~~ 'M004964%'::text) (2)テーブル同士のLIKE検索 ---------------------------------------------------------------------------- EXPLAIN SELECT wk_dss_data.comp_id, wk_dss_data.user_id FROM wk_dss_data, t_update WHERE wk_dss_data.sys_id LIKE t_update.sys_id||'%'; ---------------------------------------------------------------------------- Nested Loop (cost=157.00..12505636.00 rows=2500000 width=20) Join Filter: (("outer".sys_id)::text ~~ (("inner".sys_id)::text || '%'::text) ) -> Seq Scan on wk_dss_data (cost=0.00..5479.00 rows=100000 width=31) -> Materialize (cost=157.00..207.00 rows=5000 width=11) -> Seq Scan on t_update (cost=0.00..157.00 rows=5000 width=11)

  • Oracle 実行計画について

    数千万件が格納されているテーブルにINDEXキーを新設して そのINDEXキーを条件句にもつSQL文にヒント句をつけて必ず参照するように変更し、 実行計画を取得したら、新設したINDEXキーを参照してはいるのですが、 逆にRowsやBYTESなどが増加してしまいました。 Rows | Bytes | Cost ⇒ Rows | Bytes | Cost    1 |  23  |  5      2862 |65826 |  16 ただ、体感速度はINDEXキーを新設した方が早いです。 この場合考えられる原因とは何がありますか? Oracle11gです。

  • inの使い方について

    以下の分でなぜinが使われているかわかりません。 The actual delivery time for the item(s) in your order どちらかと言えば以下のようにofのような気がするのですが。 The actual delivery time for the item(s) of your order inはtimeにかかっていると思うのですがこれだとニュアンス的に オーダーの中の時間となり違和感があるのですが、 英語ではこれが普通なのでしょうか? The actual delivery time in your order もしそうであれば、どのようなときにこの文法が使われるか教えていただけますでしょうか? よろしくお願いいたします。 全文 You have chosen to ship your order via expedited shipping. The delivery estimate for this method to your address is 2 to 5 business days after shipping. The actual delivery time for the item(s) in your order will depend on the shipping policies of CABOARDZ and when the item(s) are available to ship.

  • インデックスについて

    テーブルは2つ ・offacc_siwakedata ・off_projectmster とあり、それぞれ下記インデックスを張っております。 create index siwakedata_index ON offacc_siwakedata( siwakedata_date, siwakedata_hdcd, siwakedata_cd, siwakedata_kamokucode, siwakedata_projectcode, siwakedata_exzankada, siwakedata_default, siwakedata_compcd, siwakedata_del ); CREATE INDEX projectmster_index ON off_projectmster( projectmster_cd, projectmster_del, projectmster_compcd ); 2つのテーブルを結合させる下記SQLを発行 explain select offacc_siwakedata.*, off_projectmster.projectmster_name from offacc_siwakedata,off_projectmster where off_projectmster.projectmster_cd=siwakedata_projectcode and off_projectmster.projectmster_del='1' and off_projectmster.projectmster_compcd='200' and siwakedata_compcd='200' and siwakedata_del='1' and siwakedata_default='1' and siwakedata_kamokucode='26300' and siwakedata_exzankada<>0 order by siwakedata_date, siwakedata_hdcd, siwakedata_cd ; explainするとoff_projectmsterのインデックスが有効になっていません。 何ででしょうか? 教えてください。 宜しくお願いします。 "Nested Loop (cost=0.00..17438.04 rows=1 width=1307)" " Join Filter: ((off_projectmster.projectmster_cd)::text = (offacc_siwakedata.siwakedata_projectcode)::text)" " -> Index Scan using siwakedata_index on offacc_siwakedata (cost=0.00..17436.98 rows=1 width=1244)" " Index Cond: (((siwakedata_kamokucode)::text = '26300'::text) AND ((siwakedata_default)::text = '1'::text) AND ((siwakedata_compcd)::text = '200'::text) AND (siwakedata_del = 1))" " Filter: (siwakedata_exzankada <> 0::numeric)" " -> Seq Scan on off_projectmster (cost=0.00..1.04 rows=1 width=96)" " Filter: ((projectmster_del = 1) AND ((projectmster_compcd)::text = '200'::text))"

  • SELECTクエリの内部動作

    以下のテーブルがあるとします table test (  id integer primary key, // ID  sex integer, // 性別(1:男, 2:女, 3:その他)  time integer, // 登録時間(unix time)  nation text // 国籍  name text, // 名前  index (id),  index (sex),  index (time),  index (group(63)),  index (name(63)) ) このテーブルに対し、 (A) SELECT * FROM test WHERE sex=2 AND nation='Japan' ORDER BY time (B) SELECT * FROM test WHERE sex=2 AND nation='Japan' ORDER BY time, id というクエリを出した際にMySQLの内部でどのように該当行を取り出しているのでしょうか? そのメカニズムに興味があります。 A, Bどちらかでもかまいません。 例えばAに関して(間違っているかもしれません) 1) timeインデックスのソート済み順序を下に、テーブル順にレコードを取り出していく 2) もし、sex=2であり nation='Japan' であれば、その行を出力 といったアルゴリズム的な部分を知りたいです。 MySQLのドキュメントでそのことについて詳しく触れている箇所や、そのようなアルゴリズム自体をご存知の方、アドバイスをお願いします。

    • ベストアンサー
    • MySQL
  • SELECT文で抽出時に複数カラムのソート方法についてご質問します。

    SELECT文で抽出時に複数カラムのソート方法についてご質問します。 開発環境は以下になります。 ・PHP Version 5.2.11 ・MySQL (5.0) そこでやりたいことです。 レストランの開店時間が、バラバラに入力されるとして 以下のデータがDBに格納されています。 TABLE `reserve` ID,NAME,DATE1,FLAG1,OPEN1,DATE2,FLAG2,OPEN2,DATE3,FLAG3,OPEN3 1,A店,2010-07-05,0,10:00,2010-07-06,1,12:00,2010-07-07,1,10:00 2,B店,2010-07-06,1,13:00,2010-07-07,1,13:00,2010-07-08,1,13:00 3,C店,2010-07-06,0,11:00,2010-07-07,0,11:00,2010-07-08,1,16:00 4,D店,2010-07-04,1,10:00,2010-07-05,0,10:00,2010-07-06,1,10:00 5,E店,2010-07-06,0,13:00,2010-07-07,1,11:00,2010-07-08,0,13:00 5,F店,2010-07-07,1,10:00,2010-07-08,0,10:00,2010-07-09,1,10:00 ・ ・ ・ 種別は ID:主キー NAME:VARCHAR DATE1~3:DATE FLAG1~3:INT OPEN1~3:TIME ※FLAG1~3は、0=店休日、1=営業日です。 ここから毎日の開店状態を、早い開店から順番に表示したいのです。 7月7日の開店状態を表示する場合の結果は 2010年07月07日 A店:10:00開店 F店:10:00開店 E店:11:00開店 B店:13:00開店 ・ ・ ・ このように、開店時間が早い順からソートして出力となります。 そこで以下のセレクト文で呼び出してみると抽出はうまくいきました。 SELECT * FROM `reserve` WHERE `DATE1` = '2010-07-07' AND `FLAG1` =1 OR `DATE2` = '2010-07-07' AND `FLAG2` =1 OR `DATE3` = '2010-07-07' AND `FLAG3` =1 しかし、ソートがうまくいきません。 ORDER BY `TIME1` , `TIME2` , `TIME3` ASC ORDER BY `TIME1` ASC , `TIME2` ASC , `TIME3` ASC ORDER BY `TIME1` `TIME2` `TIME3` ASC そこで、TIME1~TIME3をまとめてインデックスにしてみました。 でもうまくいかないです。 色々と試してみましたがうまくいきません。 根本的に間違えているのでしょうか? データを取り出してから、PHPでソートをかける方が良いのでしょうか? PHPでソートをするには、DBから取り出したデータを、連想配列に変換して ソートしてとなると思いますが。 抽出したデータを表示後、さらに店名でソートして再表示したりという ことを考えているので、出来ればSELECT文で実現したいと思い、 質問させていただきました。 ご教授いただければ幸いです。 何卒よろしくお願い致します。

    • ベストアンサー
    • MySQL
  • VBでエクセルを制御したい

    始めまして。 VBでアプリを組んでいて、指定のエクセルファイルを 操作したいのですが、うまくいきません。 ファイル指定まではうまくいったのですが、 具体的には、エクセルの指定範囲をソートしたいのですが。 Dim intR, lastR As Long intR = 2 lastR = 1000 sh.Rows(intR & ":" & lastR).Select sh.selection.Sort key1:=range(sh.Cells(intR, 5)), & _ order1:=xlascending, key2:=range(sh.Cells(intR, 1)),& _ order2:=xlascending このようなコードで実行すると、 実行時エラー438 オプジェクトはこのプロパティまたはメソッドを サポートしていません と出ます。やはりエクセルVBAと同様という簡単なものでは ないのでしょうか。 お分かりの方、お願いします。

  • VBA エラーと対策

    実行時エラー '1004' RangeクラスのSortメソッドが失敗しました。 と出ます。 With Worksheets("データ") .Range("A2:N" & .Cells(.Rows.Count, 1).End(xlUp).Row).sort _ Key1:=Range("E3"), Order1:=xlAscending, Key2:=Range("C3"), _ Order2:=xlAscending, Key3:=Range("A3"), Order3:=xlAscending End With E列、C列、A列で昇順で並び替えしようと思っております。 前まで使えていたのですが、ソートできなくなり、何が原因かわからないため、質問しました。 また、もう一つエラーがあります。 実行時エラー'-2147417848(80010108)' オートメーションエラーです。 起動されたオブジェクトはクライアントから切断されました。 と表示されます。 http://okwave.jp/qa/q8452163.html range("A1").resize(ubound(a),1) = application.transpose(a) 上記部分でエラーがでます。 上記内容で、どういった原因が考えられますか? どちらか片方でも分かる方いらっしゃいましたら、回答よろしくお願い致します。

  • 性能問題について

    set autotrace on で実行計画を見てみたのですが、 以下のテーブルAが全走査していました。 ---------------------------------------------- TABLE ACCESS (FULL) OF 'テーブルA' TABLE ACCESS (BY INDEX ROWID) OF 'テーブルB' INDEX (UNIQUE SCAN) OF 'M_KAIINP1' (UNIQUE) ---------------------------------------------- そこでオプティマイザにヒントを与えました。 ----------------------------------------------- select /*+ INDEX (テーブルA M_LINEP1) */ 項目 from ~ ----------------------------------------------- すると結果が以下のようになりました。 実行計画 ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2057 Card=27928 Byte s=5390104) 1 0 MERGE JOIN (Cost=2057 Card=27928 Bytes=5390104) 2 1 INDEX (FULL SCAN) OF 'M_LINEP1' (UNIQUE) (Cost=26 Card=4 57735 Bytes=11901110) 3 1 SORT (JOIN) (Cost=2031 Card=27928 Bytes=4663976) 4 3 TABLE ACCESS (FULL) OF 'テーブルB' (Cost=703 Card=27928 Bytes=4663976) ---------------------------------------------------------- 性能は格段に速くなったのですが、なんで速くなったのか原因がいまいちわかりません。 テーブルAとテーブルBはほぼ同じ件数(53万件程度)です。 上記を見るとテーブルAにインデックスがつけられ、テーブルBはフルで見るように変更になったと思うのですがそれだと速くなる理由がわからなくて・・・。 どなたかアドバイスお願いします。

  • 並べ替えのマクロで対象行の範囲を行を増やした分だけ可変にして増やしたい。

    マクロ超初心者です。エクセル2003においての質問です。 作成した〔日付順〕のボタンを押すことで並べ替えをしたいと思い,以下のマクロを「記録」から作成したのですが, 9行~153行の間に行を挿入した場合,並べ替えの対象となる行も同じように増えてほしいのですが,常に9行~153行のままで増えてくれません。 可能なら9行より前に行を挿入した場合も同じように可変して欲しいです。 全くのマクロ初心者でどう変えればいいのか分かりません。 また,「記録」から作成したマクロには操作内容が全て存在するようなのですが, 消してもいい不要な部分も分からないので教えて頂ければありがたいです。 よろしくお願いします。 (出来れば以下を書き直して全て貼り付けて頂けるとかなり助かります。) sub 日付順()    Rows("9:153").Select    Selection.Sort Key1:=Range("I9"),Order1:=xlAscending,Key2:=Range("J9") _       ,Order2:=xlDescending,Header:=xlGuess,OrderCustom:=1,MatchCase:= _       False,Orientation:=xlTopToBottom,SortMethod:=xlPinYin,DataOption1:= _       xlSortNormal,DataOption2:=lxSortNormal    Selection.Sort Key1:=Range("H9"),Order1:=xlAscending,Key2:=Range("B9") _       ,Order2:=xlDescending,Key3:=Range("M9"),Order3:=xlAscending,Header _       :=xlGuess,OrderCustom:=1,MatchCase:=False,Orientation:=xlTopToBottom _       ,SortMethod:=xlPinYin,DataOption1:=xlSortNormal,DataOption2:= _       xlSortNormal,DataOption3:=lxSortNormal End Sub