パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

PostgreSQL 8.0 リリース」記事へのコメント

  • 部分ロールバックも嬉しいが、とにかくVACUUMレスにして欲しい。
    あとインデックスを含んだpg_restoreの高速化とか…無理か。

    #面倒なので、OSごとHDDのミラーリング+イメージで対応してます。
    • 追記型アーキテクチャである限り、VACUUM レスは難しいだろうなぁ。その代わりに MVCC があったりロールバックセグメントの管理をしなくて良かったりするわけで (最近は Oracle も自動 UNDO 管理が普通のようですけど)、まぁここは設計上のトレードオフだと思って受け入れるしかないのでは。

      Oracle でも一つの DB をずっと使ってると行移行とかハイウォーターマークの問題とかいろいろあるわけで、データファイルの定期的なメンテナンスはいずれにせよ必須なのではないか
      • drop index→copy→create index ならば常識的な時間で処理できるんだから、内部でそれと同じことをやればいいだけだと思うんだけど…。

        それを自動でやると、複数接続から同時にユニーク制約を持ったテーブルにデータを挿入したときに、整合性を保証出

        • by bytes (17046) on 2005年01月20日 20時18分 (#681760)
          > それを自動でやると、複数接続から同時にユニーク制約を持ったテーブルにデータを挿入したときに、整合性を保証出来ません。

          確かにおっしゃる通り。
          でも実は、PostgreSQL は DDL もトランザクションに含めることが出来ちゃったりするので「drop index→copy→create index」を1つのトランザクションとして実装すれば、(最初の drop の時点でロックがかかり) 大丈夫だったりします(笑。これはほとんど裏技だなぁ。
          親コメント
          • by L.star (163) on 2005年01月20日 21時07分 (#681768) ホームページ
            いいえ、それでも元々データが1件以上入っていた場合破綻します。

            もう一つ上げておきましょう。DROP->COPY->CREATEとした場合としない場合、どっちが早いかはCOPYの量に依存しますが、当然そのシーケンスの中で、ロックを取る前にインデックス再作成した方が早いかどうかを知ることはできません。極論、レコードを1つも挿入しないのに事実上のREINDEX相当を行うというばかげた事態になります。

            ちなみに、pg_dumpもpg_restoreも、今のバージョンは全てのデータが投入されるまでindexを作成する処理は行いませんから、同等の処理は成されているはずなんですが・・・

            親コメント
            • Re:個人的には (スコア:2, 参考になる)

              by bytes (17046) on 2005年01月21日 9時57分 (#681970)
              なんだかディープな話になってますね(笑。お付き合いいただき恐縮です。

              > いいえ、それでも元々データが1件以上入っていた場合破綻します。

              そうでしょうか?ちょっとテストしてみました。

              => \d test_table
                Table "public.test_table"
              Column |  Type   | Modifiers
              ーーーーーーーーーーーーーーーー
              id     | integer |
              Indexes:
                  "test_table_id_key" unique, btree (id)

              // unique 制約だとちと面倒なので単なる unique index として用意。

              => select * from test_table;
              id
              ----
                1
              (1 row)

              => begin;
              BEGIN
              => drop index test_table_id_key;
              DROP INDEX

              // ここで他の接続から同じように begin、drop index しても
              // lock されているため待たされる。ちなみに select も待た
              // される<ダメじゃん!(笑。

              => \copy test_table from test_table.dump
              \.
              => select * from test_table;
              id
              ----
                1
                1
              (2 rows)

              // わざと unique 制約違反なデータを copy

              => create unique index test_table_id_key on test_table(id);
              ERROR:  could not create unique index
              DETAIL:  Table contains duplicated values.
              => commit;
              COMMIT

              // あれ?「WARNING:  there is no transaction in progress」
              // が出ないけど…

              => select * from test_table;
              id
              ----
                1
              (1 row)

              => \d test_table
                Table "public.test_table"
              Column |  Type   | Modifiers
              ーーーーーーーーーーーーーーーー
              id     | integer |
              Indexes:
                  "test_table_id_key" unique, btree (id)

              // ちゃんとロールバックされてる。

              なんとなく僕にはちゃんと動いているように思えるんですが (まぁ select も lock してしまっているのは置いておくとして)、どのような場合に破綻してしまうのか教えていただけますか?

              > DROP->COPY->CREATEとした場合としない場合、どっちが早いかはCOPYの量に依存します

              それはそうですね。ごく単純に上記処理を行ってしまうといろいろもったいないことが起きてしまうことは分かります。本当にシステムに組み込む場合はもう少し凝ったことをしてあげた方が良いでしょう。

              例えば、僕は上記の「drop→copy→create」が単一の import 用コマンドで行われていることを想定していますが、それならば drop 前に copy されるデータのサイズ等を知ることも可能なはずですから、それによって処理を分けるとか、

              あるいはさらに、DB 自体を工夫して「index 更新なしの copy」と「新規追加された部分のみ index 追加」を行えるようにするといったことを想像していました。

              > ちなみに、pg_dumpもpg_restoreも、今のバージョンは全てのデータが投入されるまでindexを作成する処理は行いませんから、同等の処理は成されているはずなんですが・・・

              フルダンプ、フルリストア時はさすがに考慮されているのですね。そこは未検証でした。どうもありがとうございます。

              僕の元々の書き込みは「インデックスを含むテーブルへの高速 import 手段は確かに欲しい!」ということでしたので、主に copy from が使われるような局面での高速化についての話でした。
              親コメント
              • by L.star (163) on 2005年01月21日 21時45分 (#682455) ホームページ
                ちゃんとロールバックされてる。
                ああなるほど、トランザクションでくくればデータは見えない&CREATE INDEXが失敗するので確かに整合性は維持されますね。

                ただ、UNIQUE制約のチェックが、全件insert終了後にしかかけられないため、あまりにもコストがかかりすぎているようですね。結局のところ、絶対に重複がないと確信できる状態でない限りやらない方が良さそうです。

                drop 前に copy されるデータのサイズ等を知ることも可能なはずですから
                データ量を計測したりするコストが馬鹿にならないのでは。
                「index 更新なしの copy」と「新規追加された部分のみ index 追加」
                たぶん、これらはやったところで今のCOPYの方が早いでしょう。なんとなれば、従来のindex付きcopyが「タプル挿入コスト+インデックスタプル挿入コスト」なのに、インデックス作成を遅らせたところで後で読むコストが増えるだけです。

                まあでも、この種のトランザクションを自動で発行してくれるツールがあればそれはそれで選択肢として良いのかもしれません。高速にコピーできることがあるとはいえ、その間テーブルを完全にロックしてしまうのではっきり言って使い勝手は良くないですが・・・

                親コメント
              • by bytes (17046) on 2005年01月21日 23時28分 (#682494)
                > ああなるほど、トランザクションでくくればデータは見えない&CREATE INDEXが失敗するので確かに整合性は維持されますね。

                ですです。このあたりが「裏技」っぽいなぁと(^^;

                > 結局のところ、絶対に重複がないと確信できる状態でない限りやらない方が良さそうです。
                > データ量を計測したりするコストが馬鹿にならないのでは。

                いや、おっしゃるとおりです。たぶんいろいろちゃんと考えてみると、「デフォルトの挙動を drop→copy→create に変更する」ことは難しい、という結論になるのでしょうね。

                > なんとなれば、従来のindex付きcopyが「タプル挿入コスト+インデックスタプル挿入コスト」なのに、インデックス作成を遅らせたところで後で読むコストが増えるだけです。

                ええ、ふつうに考えるとそのはずなんですけど、今の PostgreSQL の index 付き copy は常軌を逸して遅いです。大量のデータを import する場合などに、index を付けたままの copy と drop→copy→create との間で、100倍くらいの処理時間の差が生じることも普通にありますよね。理論的には読むコストが増えているはずの後者の方が遅くなってもいいはずなのに…(一件ずつインデックスを挿入する、という処理のオーバーヘッドが死ぬほど大きい、ってことかなぁ…という想像をして、「新規追加された部分のみ index 追加」ならそのオーバーヘッドを回避できたりしないかしら、と考えたわけです)。

                > まあでも、この種のトランザクションを自動で発行してくれるツールがあればそれはそれで選択肢として良いのかもしれません。高速にコピーできることがあるとはいえ、その間テーブルを完全にロックしてしまうのではっきり言って使い勝手は良くないですが・・・

                大量のデータを bulk load する場合って、たいてい一般ユーザからのアクセスは遮断して行うことが多いんじゃないでしょうか。逆にそういう状況を仮定できない場合は確かに非常に使いにくいと思います。

                大量のデータを保持しつつも更新は truncate→copy しかないような場合 (参照用 DB と更新用 DB を分けているような場合の参照側) に限れば、同じ構造を持つテーブルを2つ用意して、

                1. 裏テーブルを drop index
                2. 裏テーブルを truncate
                3. 裏テーブルに copy
                4. 裏テーブルに create index
                5. 裏と表を swap (ALTER TABLE ~ RENAME TO)

                までを一つのトランザクションとなるように処理すれば、表テーブルがロックされる時間は 5. から commit までのごくわずかな時間に抑えられます。ALTER TABLE すらトランザクションに含められる PostgreSQL ならではの裏技ですね。

                // ストレージは2倍必要になりますけどね(^^;。
                親コメント
              • by L.star (163) on 2005年01月22日 11時51分 (#682680) ホームページ
                copy付きinsertが遅いというよりcreate indexによる再作成が早いのは、indexが大きくなればなるほど1件挿入のコストが上がる、特にindex tuple作成のwal書き込みの量がかなり多くなるのが原因です。これを回避しようと8.0で一部の状況でindexのwal書き込みをしないというpatchが投げられたのですが、これはPITRなどのWALを前提としたリストア/リカバリ時にindexが壊れるから、という理由で却下されました。

                そんななので、途中からやるなら単に作成をまとめたところで状況は良くなりません。create indexの場合は最初から作るのが前提なので、作成はもっと効率よくできます。うろ覚えですが、いったんソートしてからやっていたような。

                ALTER TABLE すらトランザクションに含められる PostgreSQL ならではの裏技ですね。
                むしろこれはトランザクションを含めながらほとんどのDDLがロールバックできないと言う他DBがふがいないと思っています。

                # もちろん、あらゆるものをロールバックできる、というのは決して簡単な問題ではないので、それはトレードオフ何じゃないかな、と思わなくもないですが。

                親コメント
              • by bytes (17046) on 2005年01月23日 10時34分 (#683077)
                > そんななので、途中からやるなら単に作成をまとめたところで状況は良くなりません。

                なるほど~。そんな経緯があるのですね。非常に勉強になりました。

                > むしろこれはトランザクションを含めながらほとんどのDDLがロールバックできないと言う他DBがふがいないと思っています。

                例外の少なさや機能の直行性などに関していえば PostgreSQL は商用 DB を超える部分もありますよね。商用 DB や MySQL などと比べると進化が遅くていらいらする人もいるかもしれませんが、そういった部分こそまさにトレードオフなのかもしれないなぁ、なんてふと思いました。

                いろいろ貴重な情報ありがとうございました。 
                親コメント

「科学者は100%安全だと保証できないものは動かしてはならない」、科学者「えっ」、プログラマ「えっ」

処理中...