象と戯れ

 | 

2011-12-02

Heroku Postgresを触ってみた PostgreSQL Advent Calendar #2

16:28 | Heroku Postgresを触ってみた PostgreSQL Advent Calendar #2 - 象と戯れ を含むブックマーク はてなブックマーク - Heroku Postgresを触ってみた PostgreSQL Advent Calendar #2 - 象と戯れ

PostgreSQL Advent Calendar 12/2。もちろん日本時間で進行してます。

さてあまりディープな話しても仕方ないかなと思い、今話題絶頂渋谷女子高生の間でも噂になっていると言われるHeroku Postgresを早速使ってみた感想。ご存じない方のために念のため説明しておくと、HerokuがクラウドサービスとしてPostgreSQL単品で使えるサービスをこの間から提供しています。Database As A Serviceというやつか。

Heroku Postgres

まずはログイン。Webサービスの方は無料から始められるけど、Postgresは最低月200ドルの有料サービスなのでクレジットカードを登録。Postgresの方とWebとでシングルサインオンです。

ログインしてデータベース作成。マジで2クリックぐらいです。できあがるとこんな感じ。

f:id:umitanuki:20111201230105p:image

フルAjaxでさくさく動きます。データベース名やユーザ名、パスワードはランダム文字列が勝ってに割り振られますが、右上のConnection Settingの矢印からpsqlを選ぶとコピペでそのままシェルキックできる文字列を作ってくれます。ついでにJDBCActiveRecord用文字列も作ってくれます。

SSL必須なのでソースインストールでpsql使っているようなマニアックな方はぜひ--with-opensslでビルドしなおしてください。っていうかこのオプション指定したことなかったアルよ。あ、おしゃれな六本木のお兄さんはもちろんpgAdminとかで接続してね。

psqlでログインすると何のからくりもないバニラPostgresです。\cでtemplate1にもつながります。おもむろにCREATE DATABASEすると権限がないとおこられます。\lはこんな感じ。

dv2jnpm7g28edxm=> \l
                                               List of databases
      Name       |      Owner      | Encoding |   Collate   |    Ctype    |          Access privileges          
-----------------+-----------------+----------+-------------+-------------+-------------------------------------
 dv2jnpm7g28edxm | uv25d4bx5cii4b0 | UTF8     | en_US.UTF-8 | en_US.UTF-8 | uv25d4bx5cii4b0=CTc/uv25d4bx5cii4b0+
                 |                 |          |             |             | collectd=c/uv25d4bx5cii4b0
 postgres        | postgres        | UTF8     | en_US.UTF-8 | en_US.UTF-8 | postgres=CTc/postgres
 template0       | postgres        | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres                        +
                 |                 |          |             |             | postgres=CTc/postgres
 template1       | postgres        | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres                        +
                 |                 |          |             |             | postgres=CTc/postgres
(4 rows)

9.0でDO構文使えますので

dv2jnpm7g28edxm=> do $$ declare begin raise 'hoge'; end; $$;
ERROR:  hoge

とかも動きました。

システムカタログもpg_authidとか以外は普通に見えるので、pg_pltemplateをのぞいてみました。

dv2jnpm7g28edxm=> select * from pg_pltemplate;
  tmplname  | tmpltrusted | tmpldbacreate |      tmplhandler       |        tmplinline        |   tmplvalidator   |    tmpllibrary    | tmplacl 
------------+-------------+---------------+------------------------+--------------------------+-------------------+-------------------+---------
 plpgsql    | t           | t             | plpgsql_call_handler   | plpgsql_inline_handler   | plpgsql_validator | $libdir/plpgsql   | 
 pltcl      | t           | t             | pltcl_call_handler     |                          |                   | $libdir/pltcl     | 
 pltclu     | f           | f             | pltclu_call_handler    |                          |                   | $libdir/pltcl     | 
 plperl     | t           | t             | plperl_call_handler    | plperl_inline_handler    | plperl_validator  | $libdir/plperl    | 
 plperlu    | f           | f             | plperl_call_handler    | plperl_inline_handler    | plperl_validator  | $libdir/plperl    | 
 plpythonu  | f           | f             | plpython_call_handler  | plpython_inline_handler  |                   | $libdir/plpython  | 
 plpython2u | f           | f             | plpython_call_handler  | plpython_inline_handler  |                   | $libdir/plpython2 | 
 plpython3u | f           | f             | plpython3_call_handler | plpython3_inline_handler |                   | $libdir/plpython3 | 
(8 rows)

ん?先日の話だと「安全じゃない(untrusted)言語なんて導入できない」とか言ってたような。

dv2jnpm7g28edxm=> create language plperl;
ERROR:  could not access file "$libdir/plperl": No such file or directory

なるほど。共有オブジェクト置いてないんですね。っていうかそれならpg_pltemplateからはずしとけよって気もしますが。パッケージインストールなのかな?

そのうちここにplv8jsが並ぶわけですね。わかります。

dv2jnpm7g28edxm=> create table t(a, b, c) as select i, i % 100, repeat('x', 100 + i % 100) from generate_series(1, 1000000)i;
SELECT 1000000
Time: 23165.819 ms

dv2jnpm7g28edxm=> select pg_size_pretty(pg_database_size('dv2jnpm7g28edxm'));
 pg_size_pretty 
----------------
 189 MB
(1 row)

Time: 107.376 ms

dv2jnpm7g28edxm=> select count(*) from t;
  count  
---------
 1000000
(1 row)

Time: 937.279 ms

手元のMacBookでやったらCTASは4秒ぐらいで終わったのでやっぱり書き込みはちょっと遅いですね。もちろんWAL設定が手元はデフォルトなんですが。ただ参照は手元と同じぐらいかちょっと早いぐらい。キャッシュが1.7Gでテーブル作成は自由にできて参照もこのぐらい出るのならば、なんかもうこれでいいかって気がします。ていうかこれで最低ランクなんですが、最高ランクのMechaって誰が月6400ドルも払って数十ギガのキャッシュのせるのか。面白いから用意してみたって匂いがぷんぷんするw。

さてさて目玉はレプリケーション。ポチットな。

f:id:umitanuki:20111201230106p:image

一回失敗しましたが、二回目で完成。ログもAjaxかWebSocketか知らないけどWeb画面開いたまま更新されていきます。もちろんこのFollowerも一台につき200ドル/月。

バックアップもワンクリック。リストアは新しいDBインスタンスになる模様。金稼ぐなー。バックアップのダウンロードもリンクのクリックでダウンロード始まります。形式は-Fcですね。

あ、ちなみに料金は月極の時間単位なので、11月31日の夜にDB作って早速2ドル請求が来ました。逆に言うとこうして実験してインスタンス破棄すれば200ドルもいらないわけです。ていうかこのぐらいの性能でレプリケーション、バックアップ、リストア、ログ管理等等を全く気にしなくていいとすれば、月200でサーバ+DBAなんか雇えないわけで、十分ペイする気がします。

そんなわけで長くなりましたが、Heroku Postgres使ってみました。

明日はitagaki.takahiroさんです。よろしう。


P.S.

pg_settingsをコピペしときます。興味のある人はご覧あれ。

dv2jnpm7g28edxm=> select name, setting from pg_settings;
              name               |                                                                  setting                                                                   
---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------
 allow_system_table_mods         | off
 application_name                | psql
 archive_command                 | test -f /etc/postgresql/9.0/main/wal-e.d/ARCHIVING_OFF || envdir /etc/postgresql/9.0/resource6279_heroku_com/wal-e.d/env wal-e wal-push %p
 archive_mode                    | on
 archive_timeout                 | 60
 array_nulls                     | on
 authentication_timeout          | 60
 autovacuum                      | on
 autovacuum_analyze_scale_factor | 0.1
 autovacuum_analyze_threshold    | 50
 autovacuum_freeze_max_age       | 200000000
 autovacuum_max_workers          | 3
 autovacuum_naptime              | 60
 autovacuum_vacuum_cost_delay    | 20
 autovacuum_vacuum_cost_limit    | -1
 autovacuum_vacuum_scale_factor  | 0.2
 autovacuum_vacuum_threshold     | 50
 backslash_quote                 | safe_encoding
 bgwriter_delay                  | 200
 bgwriter_lru_maxpages           | 100
 bgwriter_lru_multiplier         | 2
 block_size                      | 8192
 bonjour                         | off
 bonjour_name                    | 
 bytea_output                    | hex
 check_function_bodies           | on
 checkpoint_completion_target    | 0.7
 checkpoint_segments             | 40
 checkpoint_timeout              | 300
 checkpoint_warning              | 30
 client_encoding                 | UTF8
 client_min_messages             | notice
 commit_delay                    | 0
 commit_siblings                 | 5
 constraint_exclusion            | partition
 cpu_index_tuple_cost            | 0.001
 cpu_operator_cost               | 0.0005
 cpu_tuple_cost                  | 0.003
 cursor_tuple_fraction           | 0.1
 custom_variable_classes         | 
 DateStyle                       | ISO, MDY
 db_user_namespace               | off
 deadlock_timeout                | 1000
 debug_assertions                | off
 debug_pretty_print              | on
 debug_print_parse               | off
 debug_print_plan                | off
 debug_print_rewritten           | off
 default_statistics_target       | 100
 default_tablespace              | 
 default_text_search_config      | pg_catalog.english
 default_transaction_isolation   | read committed
 default_transaction_read_only   | off
 default_with_oids               | off
 effective_cache_size            | 191250
 effective_io_concurrency        | 1
 enable_bitmapscan               | on
 enable_hashagg                  | on
 enable_hashjoin                 | on
 enable_indexscan                | on
 enable_material                 | on
 enable_mergejoin                | on
 enable_nestloop                 | on
 enable_seqscan                  | on
 enable_sort                     | on
 enable_tidscan                  | on
 escape_string_warning           | on
 extra_float_digits              | 0
 from_collapse_limit             | 8
 fsync                           | on
 full_page_writes                | on
 geqo                            | on
 geqo_effort                     | 5
 geqo_generations                | 0
 geqo_pool_size                  | 0
 geqo_seed                       | 0
 geqo_selection_bias             | 2
 geqo_threshold                  | 12
 gin_fuzzy_search_limit          | 0
 hot_standby                     | on
 ignore_system_indexes           | off
 integer_datetimes               | on
 IntervalStyle                   | postgres
 join_collapse_limit             | 8
 krb_caseins_users               | off
 krb_srvname                     | postgres
 lc_collate                      | en_US.UTF-8
 lc_ctype                        | en_US.UTF-8
 lc_messages                     | en_US.UTF-8
 lc_monetary                     | en_US.UTF-8
 lc_numeric                      | en_US.UTF-8
 lc_time                         | en_US.UTF-8
 listen_addresses                | *
 lo_compat_privileges            | off
 local_preload_libraries         | 
 log_autovacuum_min_duration     | -1
 log_checkpoints                 | on
 log_connections                 | off
 log_destination                 | syslog
 log_disconnections              | off
 log_duration                    | off
 log_error_verbosity             | default
 log_executor_stats              | off
 log_hostname                    | off
 log_line_prefix                 | %u [ONYX] 
 log_lock_waits                  | off
 log_min_duration_statement      | 50
 log_min_error_statement         | error
 log_min_messages                | notice
 log_parser_stats                | off
 log_planner_stats               | off
 log_rotation_age                | 1440
 log_rotation_size               | 10240
 log_statement                   | none
 log_statement_stats             | off
 log_temp_files                  | -1
 log_timezone                    | UTC
 log_truncate_on_rotation        | off
 logging_collector               | on
 maintenance_work_mem            | 65536
 max_connections                 | 500
 max_files_per_process           | 1000
 max_function_args               | 100
 max_identifier_length           | 63
 max_index_keys                  | 32
 max_locks_per_transaction       | 64
 max_prepared_transactions       | 500
 max_stack_depth                 | 2048
 max_standby_archive_delay       | -1
 max_standby_streaming_delay     | -1
 max_wal_senders                 | 10
 password_encryption             | on
 plpgsql.variable_conflict       | error
 port                            | 5432
 post_auth_delay                 | 0
 pre_auth_delay                  | 0
 random_page_cost                | 4
 search_path                     | "$user",public
 segment_size                    | 131072
 seq_page_cost                   | 1
 server_encoding                 | UTF8
 server_version                  | 9.0.5
 server_version_num              | 90005
 session_replication_role        | origin
 shared_buffers                  | 53120
 silent_mode                     | off
 sql_inheritance                 | on
 ssl                             | on
 ssl_renegotiation_limit         | 524288
 standard_conforming_strings     | off
 statement_timeout               | 0
 superuser_reserved_connections  | 3
 synchronize_seqscans            | on
 synchronous_commit              | on
 syslog_facility                 | local0
 syslog_ident                    | resource6279_heroku_com
 tcp_keepalives_count            | 9
 tcp_keepalives_idle             | 7200
 tcp_keepalives_interval         | 75
 temp_buffers                    | 1024
 temp_tablespaces                | 
 TimeZone                        | UTC
 timezone_abbreviations          | Default
 trace_notify                    | off
 trace_recovery_messages         | log
 trace_sort                      | off
 track_activities                | on
 track_activity_query_size       | 1024
 track_counts                    | on
 track_functions                 | none
 transaction_isolation           | read committed
 transaction_read_only           | off
 transform_null_equals           | off
 unix_socket_group               | 
 unix_socket_permissions         | 511
 update_process_title            | on
 vacuum_cost_delay               | 0
 vacuum_cost_limit               | 200
 vacuum_cost_page_dirty          | 20
 vacuum_cost_page_hit            | 1
 vacuum_cost_page_miss           | 10
 vacuum_defer_cleanup_age        | 0
 vacuum_freeze_min_age           | 50000000
 vacuum_freeze_table_age         | 150000000
 wal_block_size                  | 8192
 wal_buffers                     | 1024
 wal_keep_segments               | 127
 wal_level                       | hot_standby
 wal_segment_size                | 2048
 wal_sender_delay                | 200
 wal_sync_method                 | fdatasync
 wal_writer_delay                | 200
 work_mem                        | 102400
 xmlbinary                       | base64
 xmloption                       | content
 zero_damaged_pages              | off
(196 rows)

うーん。shared_buffers=53120ってことは8KBかけて400MBですね。キャッシュって何のことなんだろう。。。

 |