Postgreが重いです

このQ&Aのポイント
  • PostgreSqlを利用しております。テーブルAを作成し、URLとHPの簡単な説明を持つデータを登録しています。登録が進むとデータベースからデータを取り出し、htmlで表示するまでに50~80秒かかってしまいます。
  • 使用しているプログラム言語はPerlで、データベースへのアクセスにはPgモジュールを使用しています。ただし、レンタルサーバであるため、Postgreのバージョンやサーバのスペックなどはわかっていません。
  • 質問ですが、5万件程度のデータ登録でPostgreが重くなるのか、それともサーバの設定の問題なのか知りたいです。
回答を見る
  • ベストアンサー

Postgreが重いです

PostgreSqlを利用しております。 テーブルAを作成し、テーブルにはURL、HPの簡単な説明をもっております。 HPデータを5万件程度登録したあたりで、 データベースからデータを取り出し、htmlで表示するまで50~80秒 程度時間がかかってしまいます。 プログラム言語はPerl、DBへのアクセスはPgモジュールを使用して おります。 レンタルサーバであるため、Postgreのバージョン、サーバスペック 等はわかっておりません。 ※他のユーザと共用サーバであることは間違いないのですが。 有識者様にご質問ですが、Postgreは5万件程度の登録で動作 が重くなるのでしょうか? それとも、サーバの設定の問題でしょうか?

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

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

#1、#2回答者です。 >仮にhp_body、hp_urlにindexを指定する場合、 >create index hp_table_ix1 on hp_table(hp_timestamp, hp_body, >hp_url) >とすればよいのでしょうか? 3列でインデクスを構成したければ、そういう指定になります。 インデクスを利用し性能を出すための検索条件等の書き方と、インデクスの定義方法はお分かりですか? 不必要なインデクスを定義すると、insert、update、deleteでは、オーバヘッドになってしまいます。 なお、primary keyを指定した列には、PostgreSQLがユニークチェックするために内部的にインデクスを定義します。したがって、同じ構成列のインデクスを定義するのは、更新処理等でオーバーヘッドになるだけです。 インデクスの有効利用について、いくつか例を示します。 なお、データ件数が相当に少ない(100件とか)場合は、PostgreSQLに「インデクスを使うより、表データを直接見た方が早い」と判断される場合があります。 また、analyze文等でコスト情報(重複度合いなど)を収集している場合は、以下の説明とは違ってくる場合があります。 <例1>単一列でインデクスを構成 (1)インデクスの定義 create index t1ix1 on t1(c1) (2)インデクスを有効に利用できる検索  次のような検索で、インデクスを有効利用できます。 select * from t1 where c1='a' -- =条件 select * from t1 where c1 between 'a' and 'z' -- 範囲条件 select * from t1 where c1 like 'a%' -- 前方一致 select * from t1 where c1 in('a','b','c') -- in条件 また、以下のような操作でも、インデクスが活用されます。 select sum(c1) from t1 -- 集合(集計)関数 select * from t1 order by c1 -- ソートやグループの指定 select * from t1 order by c1 limit 100 offset 100 -- limit、offsetは有効利用できるインデクスがないと、表のデータ部を空読みして読み飛ばすことになる。インデクスが利用できれば、インデクス上で読み飛ばしできる。 インデクスを有効利用できる検索条件と、利用できない検索条件があった場合は、インデクスで絞り込んだ後、表の格納データで条件が評価されます。 select * from t1 where c1='a' and c2>100 また、ソート(order by)やグループ指定(group by)、重複排除(distinct)指定時、利用できるインデクスがないと、表データを見てソートが行われることになります。 (検索条件でデータが絞り込まれている場合は、そのデータのみ) select * from t1 order by c2 <例2>複数列でインデクスを構成 (1)インデクスの定義 create index t1ix2 on t1(c1,c2,c3) (2)インデクスを有効に利用できる検索  次のような検索で、インデクスを有効利用できます。 select * from t1 where c1='a' -- インデクスを構成する先頭列にインデクスを有効利用できる条件あり。 ただし、この検索の場合はc1だけのインデクスがあればいいので、c1~c3でインデクスを構成していた場合、キー長が長くなる分、1個のインデクスページで管理できる情報数が少なくなり、インデクスのI/Oは多くなります。 select * from t1 where c1='a' and c2=100 -- インデクスを構成する先頭列に加え、他の構成列も、インデクスを有効利用できる条件あり select * from t1 where c1='a' and c2=100 and c3>50 select * from t1 where c1='a' and c3>50 -- c2の条件がない場合、インデクスの利用効率はc2の条件がある場合比べ悪い select * from t1 where c1 between 'a' and 'z' order by c1,c2 -- 条件式で絞り込む以外に、ソート指定がインデクス構成列と同じ並び(昇順、降順は、まったく同じor全部逆)であればソート抑止できる。group byやdistinctの背景でもソートが行われるので、その場合も同様。

kurea_kurea
質問者

お礼

このたびはありがとうございました! おかげさまで動作が軽くなりました! 非常にわかりやすいご解答ありがとうございます。

その他の回答 (2)

回答No.2

#1回答者です。 >hp_timestamp datetime, // 登録日 datetime型? PostgreSQLには、datetime型はないようですが? timestamp型の誤りでしょうか? >select * from hp_table ORDER BY hp_timestamp DESC LIMIT 20 現在の表&インデクス定義で、このSQLがどういう動きをするか、お分かりですか? このselect文を実行するたびに、全件(現在は5万件)をhp_timestamp列の値でソートし、その結果から最新の値を20件だけ取り出すことになります。 毎回、全件のソートが発生しますから、データが増えるごとにどんどん遅くなって当然のSQLになっています。 対策としては、hp_timestamp列にインデクスを定義しましょう。 次のSQLを実行します。 create index hp_table_ix1 on hp_table(hp_timestamp) hp_table_ix1はインデクス名であり、好きな名前にしてください。 データが格納された状態でインデクスを定義するので、実行に少し時間が掛かると思いますが、その後の今回のselect文の実行は、劇的に早くなり、データ件数が増えても、極端に性能劣化することはないでしょう。 ※上記のcreate indexでは、hp_timestamp列の値の昇順でインデクスを作りますが、降順にも活用できます。 また、text型を使用していますが、text型を使用するのは、 「検索時の条件に指定しない」 & 「長さの上限がどうしても事前に把握できない」 場合だけにし、なるべくvarcharを使用しましょう。 text型にインデクスを定義できなっかたり、定義できても検索時に有効利用できないRDBMSが殆どです。

kurea_kurea
質問者

補足

ご解答ありがとうございます。 >datetime型? >PostgreSQLには、datetime型はないようですが? >timestamp型の誤りでしょうか? timestamp型の間違いです。 申し訳ございません。 もう一点ご教授願います。 仮にhp_body、hp_urlにindexを指定する場合、 create index hp_table_ix1 on hp_table(hp_timestamp, hp_body, hp_url) とすればよいのでしょうか?

回答No.1

PostgreSQLのバージョンは、SQLが入力できる状態で 「select version()」 を入力すれば得られます。 表を構成する各列のデータ型は、何になっていますか? どういうインデクスを、この表に定義していますか? >5万件程度登録したあたりで、データベースからデータを取り出し、 >htmlで表示するまで50~80秒程度時間がかかってしまいます 5万件中、何件を取り出そうとしているのですか? その時の検索条件、ソートの指定(order by)は、インデクスを有効利用できる指定になっていますか? ・表及びインデクスの定義(各列のデータ型も分かるように ・検索時のSQL ・5万件中、何件の検索か? といった情報がなければ、使い方の問題なのか、サーバ等の問題なのかといった切り分けはできません。

kurea_kurea
質問者

補足

ご解答ありがとうございます。 データの方は以下となっております。 上記ではすこし省略しましたが、全部記載します。 ■テーブル: CREATE TABLE hp_table(  no serial primary key, // 項番  Category int4, // カテゴリNo  hp_name text, // HP名  hp_body text, // HPの説明  hp_url text, // URL  hp_timestamp datetime, // 登録日  flg int2 // 表示/表示判定フラグ(0、1) );  ※すいませんインデックスが分かっていないのですが   どうやれば使用できるのでしょうか? ■検索時のSQL: select * from hp_table ORDER BY hp_timestamp DESC LIMIT 20; 上記sqlの通り、5万件中20件の表示となっていります。 申し訳ないのですが宜しくお願い致します。

関連するQ&A

  • 【PostgreからSQL-ServerのテーブルをSelect】

    【PostgreからSQL-ServerのテーブルをSelect】 PostgreからSQL-ServerのDBにあるテーブルをSelectしたいのですが、 ODBCまでは設定したものの、それ以降のやり方がわかりません。 どなたか教えていただけないでしょうか。 【参照元】 *Windows 2003 ServerR2(32Bit) *SQL-Server 2005 【参照先】 *Windows 2003 ServerR2(32bit) *PostgreSQL 8.2 参照先と参照元を変更すればSQL-Server上で出来そうなのですが、 今回、Postgre側からSQL-ServerにSelectしなければなりません。 OracleでいうところのDB Linkなのですが、どなたか教えていただけないでしょうか。 URLのご提示でも結構です。 どうぞよろしくお願いいたします。 Postgre ---- Select(後にViewに変更予定) ----→ SQL-Server

  • postgreのDBデータを、丸ごとAccessに移行する方法って?

    Linuxサーバで稼動しているpostgre/DBのデータベースに入っているテーブルやそのデータを、 WindowsのAccessに取り込みたいのですが、何か方法はあるでしょうか?

  • php + postgre で接続できない

    php + postgre 初心者です。 Windows環境で作成しています。 データベースに接続できません。 エラー内容 Fatal error: Call to undefined function: pg_connect() in c:\home\php2\pgbbs1.php on line 13 pg_connect()関数が利用できないらしいのですが、 何か設定が必要ですか? PostgreSQLのモジュールをインストールする必要があるのですか? Windws環境で何をどのようにインストールしていいのかわかりません。 わかりやすいサイト等ありましたら教えてください。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • DB(Postgre)について、知っている方ご教授願います。

    DB(Postgre)について、知っている方ご教授願います。 Versionは8.3.Xです。 C/Sのシステムなのですが、クライアントからサーバーの更新系テーブル(更新TBL)に随時書き込んでいます。Postgreの機能を使い、更新TBLと同一のTBL(更新1_TBL)を自動で作成することは可能でしょうか? [CL]    [SRV] データ -> 更新_TBL ・・・ (1)     -> 更新1_TBL ・・・ (2) (1)を実行すると(2)が自動的に出来る機能ってありますか? (レプリケーションのテーブル版みたいな機能ってありますか?)

  • phpからPostgreにconnectで失敗

    DBサーバーに対して、WEBサーバーからアクセスしています。 同じphpソースで同じDBにアクセスしているのに一方はconnectに成功して、一方は失敗します。 <前提> インターネット上のDBサーバーにPostgreSqlがあります。 それとは別のローカルWEBサーバーのphpからPostgreSqlのデータを読んでいてこれは上手く行っています。 ローカルWEBサーバーのコピー環境をインターネット上に立てようとしていますが、これが上手く行きません。 <DBサーバー> OS:CentOS7 dbms:PostgreSql host:dbserver.net port:5432 user:user1 password:password1 dbname:db1 設定ファイル /var/lib/pgsql/data/pg_hba.conf # PostgreSQL Client Authentication Configuration File # TYPE DATABASE USER ADDRESS METHOD host all user1 0.0.0.0/0 md5 設定ファイル # /var/lib/pgsql/data/postgresql.conf listen_addresses = '*' port = 5432 <ローカルWEBサーバー> host:test.local OS:CentOS7 Server version: Apache/2.4.6 (CentOS) Server built: Oct 19 2017 20:39:16 PHP 5.4.16 (cli) (built: Nov 15 2017 16:33:54) Copyright (c) 1997-2013 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies <php中のコネクト部分> <?PHP // PostgreSQL 接続をオープンする $dbconn = pg_connect("host=dbserver.net port=5432 user=user1 password=password1 dbname=db1");  :  :  : <セットアップ中のWEBサーバー> host:test.com OS:CentOS7 Server version: Apache/2.4.6 (CentOS) Server built: Oct 19 2017 20:39:16 PHP 5.4.16 (cli) (built: Nov 15 2017 16:33:54) Copyright (c) 1997-2013 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies <セットアップ中のWEBサーバーでのエラー> Warning: pg_connect(): Unable to connect to PostgreSQL server: could not connect to server: Permission denied Is the server running on host 同じ事をしているのに、どうして一方はconnectに失敗するのでしょうか?

    • ベストアンサー
    • PHP
  • PHPとPostgreSQLがつながらない

    PHPとPostgreSQLの初心者です。PHPとPostgreSQLを 使ってプログラムを作ろうと思ってます。 開発はPC上で、PostgreとPHPサーバはLinuxマシンに あります。まず最初にPostgreのインストールですが、 Fedora Core5 に着いていたPotsgreSQL8.1.3を入れ ました。設定としては、 postgresql.confでは listen_address='localhost,192.168.1.3' としました。192.168.1.3はLinuxマシンのローカル アドレスです。 pg_hba.confではconnectionのところで host all all 192.168.1.3 255.255.255.0 tyust としました。その後 host all all 0.0.0.0 255.255.255.0 tyust とかいろいろ試してみました。 一方PHPの方はほとんど何も設定をしていません。と いうか設定方法がよくわかりません。 以上の環境で、簡単なPHPプログラムをPostgreにつなげないで実行したところ問題なく動きました。 20行くらいのPHPを書いてみましたが、特に問題はあ りませんでした。 PostgreSQLの方は、PCからSSHで入って、接続テスト 用のDBを作り、テーブルも3つ作って、データを数件 Insertしました。 いよいよPHPからDBにつなぐことになったのですが、 プログラム上では以下のように書きました。 <?php    print "こんにちは"; $conn = pg_connect ('host=192.168.1.3 port=5432 dbname=phptest user=postgres');    print "こんばんは"; if (!$conn) { print "PostgreSQLへの接続に失敗です"; exit(); } else ・ ・ して実行したところ、「こんにちは」は表示されま したが、「こんばんは」以下はは表示しませんで した。$conn の先には進んでいないようです。 当然ここに書いた以外にも設定を変えてみましたが、 つながりませんでした。よろしくお願いします。

    • 締切済み
    • PHP
  • DBI DBD::Pg 等のPerlモジュール・ドライバのインストールについて

    はじめまして。 Perlが稼動するWebサーバーと Postgreが稼動するDBサーバーと物理的に2台に分けた サーバー環境上での質問です。 DBI DBD::Pg Net::SMTP という3つをインストールしようと思うのですが、 どれをどちら(WebかDBか)のサーバーに 入れてよいのか判別がつきません。 (今まで1つのサーバー上で稼動させていた事がありますが) 理屈で考えれば、Perl上で動かすものだから すべてWebサーバーにインストールすればいいような気がする のですが・・・。 どなたかご存知の方、ぜひ教えてください。

  • 改行がはいったデータでエラー?

    サーバを変更することになり、PostgreのDBも移行することになりました。 Postgreのバージョンは 現在:7.1.3 新:8.1.4 です。 現在のDBのダンプファイルを作成し、 新しいDBにリストアしたのですが、 いくつかのテーブルでエラーがでて、 データのコピーができませんでした。 (テーブルは作成できましたが、データなく、空です。) エラーがでたテーブルには、どれも改行のはいったデータがあるので、 これが原因ではないかと思うのですが、 改行の入ったデータは何か問題があるのでしょうか? また、もし改行が原因であれば 何か解決策はありますでしょうか? 以上、よろしくお願いいたします。

  • 別のサーバーにあるDBに対してSELECTした結果が帰ってこない。

    別のサーバーにあるDBに対してSELECTした結果が帰ってこない。 質問はタイトル通り、別のサーバーにあるDBに対してSELECTした結果が帰ってきません。 あるwebサイトを新しいサーバーに移行する事になりました。 データベースはwebサイトと同じサーバーに準備していたのですが 新しいサーバーに移行する際に別のサーバーに準備する事になりました。 そして新しい環境で動作検証をしていて特に問題なく進んでいたのですが・・・・ 旧環境では特に問題なくSELECTした結果が帰ってきていましたが 新しい環境ではデータ取得の際に件数が多くなるとSELECTした結果が帰ってきませんでした。 SELECTした結果は約7000件~30000件のデータを取得するようになっております。 (新しい環境で1000件近くのデータを取得しようとしたら約5分かかりました。) これはSQL文が悪いのでしょうか、それともphpの設定が悪いのか、postgresqlの設定が 悪いのか特定出来ずに困り果てております。。。 何でも構いませんのでご助言を頂けたら幸いです。 ■環境について □以前の環境 同じサーバー内にphpとpostgresqlがある Postgresqlのバージョンは8.0.3で、phpのバージョンは5.0.5です。 □現在の環境 別のサーバーにphpとpostgresqlがある Postgresqlのバージョンは8.1.18で、phpのバージョンは5.1.6です。 ■データ取得テーブル □テーブル名 テストテーブル □フィールド数 100 (登録時刻フィールドはタイムスタンプ型です) □SQL文例 Select * From テストテーブル Where 登録時刻フィールド >= 'yyyy-mm-dd' AND 登録時刻フィールド <= 'yyyy-mm-dd'

  • pg_dumpallのやり方がわからない・・・涙

    皆さんよろしくお願いします。 現在当方windowsXP & Postgresql8.1にてサーバを構築しております。 サイトが完成したのでそろそろDB全体のバックUPを行いたいのですが、 windowsでpg_dumpallを実行するにはどうすればいいのでしょうか?? 1からわからないので出来るだけ詳しく教えていただけるでしょうか?? よろしくお願いします。m(__)m 【追伸】 pg_dumpallってテーブル構成やユーザー以外にも格納されている データもバックUPされるのですよね??