• 締切済み

単純なselectが遅くなるのですが、理由がサッパリわかりません

初めて投稿させて頂きます。 過去に、PostgreSQL 7.4.6(Linux 2.6.9-5.EL)の環境で、データ監視系のシステムを構築しました。稼働してから数年が経過しています。 このシステムのDBには数十のテーブルがあり、期待通りに動いています。 ただ、一つのテーブルのみ、時間が経過の経過と共にselectが恐ろしく遅くなる現象が発生しています。 そのテーブルのスキーマは以下です。 =# \d node_condition; Table "public.node_condition" Column | Type | Modifiers ------------------+-----------------------------+----------- node_id | integer | checktime | timestamp without time zone | ping | boolean | rtt | real | cpu | real | loadavg | real | mem | real | disk | real | snmp_w | integer | ip_w | integer | serv_w | integer | licence | integer | f_licence | integer | version | text | web_ver | text | sync | boolean | errchecktime | timestamp without time zone | ipwatchtime | timestamp without time zone | servwatchtime | timestamp without time zone | nmsdlasttime | timestamp without time zone | filemakelasttime | timestamp without time zone | 現在入力されているデータ数は51ラインです。 設計上、このテーブルは約1分間に51回updateが行われます。 主に時間系の更新です。 他のテーブルと違うところは、カラム数が少し多い、updateが頻繁に実行される、というくらいです。他のテーブルは多くても12カラムで、子のような現象は出ていません。 SQL(select)は至ってシンプルで、このテーブルしか参照しません。(select node_id,checktime ... from node_condition;) 構築時の応答速度は至って普通だったのですが、昨年の夏に異常に遅くなっていることが判明しました。 その時は、データを退避してからテーブルをDROPしてcreateし直すという荒業で解決したのですが、先日また異常に遅くなっている事に気づきました。 (この時点で原因を潰すべきだったのですが、忙しくて強引にやってしまいました。ちなみに、その時VACUUM,ANALYZEはやったのですが、効果がありませんでした。また、このシステムではVACUUM,ANALYZEが定期的に実行されています。) postgresはupdateのアルゴリズムは、他のRDBMSと違うような事が書いてありましたが、カラム数が多くなると挙動に影響が出るのでしょうか。どなたか詳しい方がいましたら、ご教授頂けると助かります。

みんなの回答

  • yamada59
  • ベストアンサー率74% (29/39)
回答No.2

定期的にVACUUMを実行しているにも係わらず、時間の経過とともに51件しかデータの格納されていないテーブルのSELECTが遅くなるとしたら、空き領域マップ(FSM)のページ数が不足していることが原因として考えられます。 FSMのページ数が不足していると、VACUUMを実行してもUPDATEで発生したゴミの領域を再利用できるようにならず、どんどんテーブルファイルが大きくなって性能が低下します。 VACUUMの実行時にVERBOSEオプションを指定すると、必要なページ数が表示されます。そのページ数がpostgresql.confファイルのmax_fsm_pagesパラメータの値よりも大きければビンゴです。 max_fsm_pagesパラメータの値を大きくして PostgreSQL を再起動し、テーブルを再作成してデータをリストアしなおすか、VACUUM FULLでテーブルファイルのサイズを小さくしてください。そうすれば性能が改善されるかもしれません。

nemotoko
質問者

お礼

ご回答ありがとうございます。 稚拙な質問文にもかかわらず、適切なご意見を頂きまして恐縮です。 FSMのページ数ですか、、、初めて聞きました。 この辺のパラメータは知ってからDBMSを使え!って怒られそうですけど・・・ 今度現場に行った時に調査して見ます。 少し時間が空くかもしれませんが、必ず結果をご報告します。

回答No.1

質問内容が、漠然としすぎです。 >ただ、一つのテーブルのみ、時間が経過の経過と共にselectが恐ろしく遅くなる >構築時の応答速度は至って普通だったのですが、昨年の夏に異常に遅くなっていることが判明 「恐ろしく遅い」、「普通だったが、・・・異常に遅くなった」などと書かれても、具体的な説明なしに他人にアドバイスできると思いますか? >現在入力されているデータ数は51ラインです。 >設計上、このテーブルは約1分間に51回updateが行われます 51ラインとは? 母体データが51件と、言っている訳ではないのですよね? 51回updateとは、母体データ何件に対し、何件のupdateを何回やると言ってますか? どんな検索条件を指定し、どの列をどのようにupdateするのでしょうか? >SQL(select)は至ってシンプルで、このテーブルしか参照しません。(select node_id,checktime ... from node_condition;) 検索条件なしで、全件検索をやると言ってますか? 関数の使用、order by、distinctやgroup byなどもないのですか? 時間の経過と伴に性能劣化するなら、普通に考えればインデクスを有効利用できていないのでしょうが、提示された内容から判断は無理です。

nemotoko
質問者

補足

すみません・・・ 説明がなってませんよね。 まず、「恐ろしく遅い」ですが、構築時はクエリ完了までに0.0secで返ってきていたのですが、運用するにつれて20.0sec程度掛かるようになっています。 次にテーブルについてですが、現在51件入力されている状態です。 この51件のデータには、それぞれIDが付いていて、その51件に対して1分間に1回ずつupdateされるようになっています。具体的には、 update node_condition set checktime = '2010/02/10 10:01:00' where node_id = 1; です。 selectは検索条件無しです。本当に初心者本の最初に載っているようなselect文です。ソート系やプロシージャも無しです。 INDEXも使っていません(51件程度しか入らないテーブルなので) というように幼稚な設計部分なので、この現象自体が逆に不思議なのです。SQLの組み直しをする余地も無いんです。 なので、postgres側に何か重大な欠陥でもあるのかなと思って皆様のお知恵をお借りしようと思った次第です。 拙い説明で申し訳無いですが、アドバイス頂けると幸いです。

関連するQ&A

  • timestamp が空のデータを除いて、データを選択したい

    テスト用に簡単なテーブルを作成してみました。 テーブル名:timetest フィールド: test_id : integer NOT NULL test_date : timestamp without time zone テストデータとして 1,2005-11-15 14:01:40.026 2,NULL 3,2005-11-14 11:11:11.001 このときに test_date がNULL以外のものだけを選択したいのですが、 slect * from timetest where test_date != null; では1件も選択されず、 select * from timetest where test_date != ''; では、 ERROR: invalid input syntax for type timestamp: "" というエラーになってしました。 どなたかご教授お願い致します。

  • 大量データを更新したら、処理速度が低下した時の対応

    お世話になります。 PostgreSQLにて、大量データ(40万件ぐらい)のテーブルに、下記処理を行ったところ、処理速度が異様に低下してしまいました。 ・10行くらいのカラムを追加 ・デフォルト値制約を設定 ・追加したカラムにデフォルト値をアップデート 一応、VACUUM ANALYZEは、かけてはいたのですが、処理速度は向上せずに、VACUUM FULLにて対応したところ、速度は元に戻りました。 ですが、カラム追加をする毎にVACUUM FULLをかけるには、ちょっと時間がかかり過ぎで、他に良い方法が無いか悩んでおります。 何か、良い方法はありませんでしょうか? 宜しくお願い致します。

  • PostgreSQLのテーブル構造を取得したい

    現在PostgreSQLとPHP5を利用してアプリケーションを開発しております。 PHPにて現在すでに存在するPostgreSQLのテーブルの定義情報を取得するにはどうすればよろしいでしょうか。テーブルの定義情報は下記のようにSQLのCREATE文で取得したいと思っております。 CREATE TABLE favorite ( code serial NOT NULL, reg_date timestamp without time zone NOT NULL DEFAULT now(), update_date timestamp without time zone, title text, url text, u_id character varying(20) NOT NULL, enabled_flag smallint NOT NULL DEFAULT 1, CONSTRAINT web_favorite_pkey PRIMARY KEY (fv_code) ) 何卒よろしくお願いいたします。

  • PostgreSQLからMySQLへ変換

    現在ECサイトに追加カスタマイズ機能を導入したいと考えているのですが、 その際の使用コードが以下のようにPostgreSQLの記載となっており、 使用しているphpMyAdminにてSQLコードを入力するとエラーとなってしまいます。 ↓PostgreSQLコード CREATE TABLE dtb_bookmark ( bookmark_id serial NOT NULL, customer_id integer NOT NULL, product_id integer NOT NULL, memo text, create_date timestamp without time zone NOT NULL, update_date timestamp without time zone NOT NULL, del_flg integer ); ALTER TABLE ONLY dtb_bookmark ADD CONSTRAINT dtb_bookmark_pkey PRIMARY KEY (bookmark_id); COMMENT ON TABLE dtb_bookmark IS 'お気に入り情報'; エラーはtimestamp型とALTER以降の文で発生致します。 mysql文にて解釈させるにはどのように変更したらよろしいのでしょうか? 使用mysqlバージョンはMySQL 4.1.21です。 アドバイスなど頂けましたら幸いです。 よろしくお願い致します。

    • ベストアンサー
    • MySQL
  • [MYSQL]TIMESTAMPをWHERE句に指定しUPDATEする方法

    以下のようにテーブルを作成し、TIMESTAMP型のカラムをキーにUPDATEをしたいと考えています。 create table test(time timestamp, amount int); insert into test values('2008-01-07 19:15:12',0); update test set amount = -1 where time = '2008-01-07 19:15:12'; ところがMYSQLではUPDATE後、TIMESTAMPのカラムが2008年から2009年に変化します。ORACLEで試しましたが、TIMESTAMP型のカラムは変わりませんでした。 +---------------------+--------+ | time | amount | +---------------------+--------+ | 2009-06-30 10:04:53 | -1 | +---------------------+--------+ MYSQLの独自の仕様があるのでしょうか? MYSQL 5.1.35(mysql-essential-5.1.35-win32.msi) Windows 2003 Server Standard Edition R2 MYISAM

    • ベストアンサー
    • MySQL
  • VACUUM ANALYZE の頻度について

    表題の件について質問させてください。 環境は PostgreSQL8.2.1 pgpoolにてDB2台で運用しております。 現在、とあるECサイトの運用などに携わっております。 1日平均が2~3千件の注文があり、注文情報を格納してるテーブルが150万件くらいになっています。 元々の作りが全てその注文テーブルに色々な情報を持たせてしまっており、更新頻度も結構高いです。 その状態で、現在は3時間に1回VACUUM ANALYZEをかけているのですが、その影響かはわからないのですが、セッション数(pg_stat_activityの件数)が正常運用時の3倍程度になる事が、ここ最近頻発しており、サイト全体の処理速度に影響しております。 1.VACUUM ANALYZEは、ロックがかからずにSELECT,UPDATE,INSERTなどが出来ると認識しておりますが、実行中に更新がかかっても問題ないという認識はあっておりますでしょうか? ロックがかかったまま、セッションに残ってしまっているのは別の原因という事であっていますでしょうか? 2.VACUUM ANALYZEの頻度として、3時間に1回という頻度は多いのでしょうか? やはり、pg_stat_activityで監視をしていると、VACUUM ANALYZEの処理に時間がかかって、セッション数が多くなり、処理速度にかなり影響をあたえているのでは無いかと言う気がしてなりません。 以上、2点について、何かご教授頂ければ幸いです。 宜しくお願い致します。

  • PostgreSqlについて

    おはようございます。 質問させてください。 テーブルのカラムにtimestamp型のフィールドがあるとします。 テーブルinsertの時に現在の時間をいれたいのですが、どのような値を入れればいいのでしょうか? test_tbl-------------- ID:INTEGER DATE:TIMESTAMP ---------------------- insert into test_tbl (ID, DATE) values (1, ****); ****の部分にnow, dateとかそんな関数はあるのでしょうか?

  • TIMESTAMP型が含まれるテーブルの列名の取得

    Oracle 11gを使用しているSQL初心者です。 テーブルの列名を取得する方法についての質問です。 テーブルの列名を取得するときは以下のSQLで取れると思っています。 select column_name from user_tab_columns where table_name = 'テーブル名'; --実行結果-- COLUMN_NAME ------------------------------ NAME1 NAME2 しかし、テーブルにTIMESTAMP型が含まれていると 「レコードが選択されませんでした。」 と表示されます。 TIMESTAMP型が含まれるテーブルは上記のSQLでは取得できないのでしょうか。 TIMESTAMP型が含まれるテーブルの列名の取得方法をご存知の方がいらっしゃいましたら、 ご教示ください。よろしくお願い致します。

  • UNIQUEをつけたときのINDEXテーブル

    テーブル作成時、カラムにUNIQUEをつけると自動でインデックステーブルが作成されますが、このインデックステーブルで、通常のselect検索も早くなるのでしょうか? 具体的には、ユニークなカラムidを持つテーブルtableA create table tableA( id INTEGER UNIQUE, some_column INTEGER ); を作ったあとで、そのidにあらためて CREATE INDEX id ON tableA (id); と、インデックスを張る必要があるのでしょうか。 よろしくお願いします。

  • Mysql(5.1)を利用してWebアプリケーションを作成しているので

    Mysql(5.1)を利用してWebアプリケーションを作成しているのですが、ユーザマスタのテーブルを作成する時に、カラム ユーザIDにAUTO_INCREMENTにした場合、他のカラム 登録者ユーザID ENTRY_USER_ID、更新ユーザID UPDATE_USER_IDにもAUTO_INCREMENTを指定したいのですがエラーになってCREATEできません。 エラーが表示されます。 ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key ぐぐって見たのですが、プライマリーキーなどといっしょに指定するみたいなのですが、SQL文は、create table USER_MST ( USER_ID INTEGER(10) AUTO_INCREMENT, NICKNAME VARCHAR(12) NOT NULL, ENTRY_USER_ID INTEGER(10) AUTO_INCREMENT, UPDATE_USER_ID INTEGER(10) AUTO_INCREMENT, ENTRY_YMD TIMESTAMP NOT NULL, UPDATE_YMD TIMESTAMP NOT NULL, DELETE_YMD TIMESTAMP NULL, PRIMARY KEY ( USER_ID ,ENTRY_USER_ID,UPDATE_USER_ID) )ENGINE=InnoDB CHARACTER SET UTF8; を実行しているのですが、うまくいきません。 ご教授お願いします