back
69 comments
Having recently been bitten by a 20 hour schema change to a very large table in MySQL I have been looking at Postgresql more seriously.

My biggest issue with it having used it for other projects is getting the dammed thing setup and working to begin with. I could never find a decent tutorial (or rather one that fits my mindset) of how to do the following,

1. Install 2. Setup users, including how to set it up on a local development machine with 'root' user who can do anything (saves time in dev) 3. Import/Export SQL/Backup files

I managed to do all 3. Once.

I'm sure its out there, and I would switch in a heartbeat were these steps much easier to work out. As it is I can just copy the table, run the alter in the background and rename the tables the next day. Slower, but doesn't cost me any time and works.

The bootstrap is not really hard when you've done it once, just jot it down somewhere.

In my experience most people stumble because the network security in postgres is pretty tight by default.

This is easily fixed and needs to be done only once.

First: Find your pg_hba.conf. It's in the database-directory, that's often linked to /etc/postgresql.

  # Backup the original
  $ cp pg_hba.conf pg_hba.conf_orig

  # Now replace it with our desired security settings
  $ cat >pg_hba.conf <<EOF
  # Require password auth from remote hosts
  # localhost and local socket are trusted
  host  all all 0.0.0.0/0 md5
  local all all trust
  host  all all 127.0.0.1/32 trust
  EOF

  # restart
  $ /etc/init.d/postgresql restart
From now on you can connect as any user from localhost without a password. Thus, we can now just go about our business.

  # connect as user postgres (the super-user)
  $ psql -U postgres
  postgres=# create database dummy;
  postgres=# create user bob with password 'pony';
  postgres=# grant all on database dummy to bob;
  postgres=# ^D

  # Now you have a database that user bob can use.
  # From remote he will have to use the password 'pony'.
  # From localhost no password needed because of our pg_hba settings above.
  $ psql -U bob dummy
  bob=> create table ...
Note: You need not restart PostgreSQL after changing pg_hba.conf. This is enough:

  /etc/init.d/postgresql reload
I would be wary about trusting all connections from localhost. As vulnerabilities are many, getting a local unprivileged shell isn't exactly hard and as opening a socket connection isn't exactly a privileged operation.. you could expose yourself to a nasty bootstrap attack. Probably better to trust the local unix domain socket, and make it accessible by root only... if you really need it.
I would be wary about trusting all connections from localhost.

The only place where this is an issue would be hosts with multiple untrusted users, and these are becoming very rare.

getting a local unprivileged shell isn't exactly hard

Sorry, that's nonsense. The entire internet relies on the fact that this is relatively hard, unless you neglect basic security precautions.

Alternately, you can use sameuser privs at the local socket level, which will allow unix user foo access to Postgres user foo without a password, but only on the domain socket. That's probably the best combination of ease of use and moderate security for a dev system.
That looks too be exactly what I have been missing. I have yet to see details like that not spread out over 5 pages. Thank you!
Yes, the docs could use indeed a few lighter tutorials for people starting out.

However, once you're over that initial learning hump and start looking for more specific things you'll quickly notice why the postgres manual is often cited as being one of the best documentations ever written (inside and outside the OSS world). It's really that good - once you're familiar with a few basics.

What is your platform? If it is Debian then it is as simple as this to install PostgreSQL and set up a PostgreSQL root user with the same username as your UNIX username (this to avoid having to modify pg_hba and and also not having to specify user when connecting to PostgreSQL).

  sudo apt-get install postgresql
  sudo -u postgres createuser -s `whoami`
After this you an just create a database and connect to it with:

  createdb my_db
  psql my_db
Usually Ubuntu, so I will have a look at this. However when running an application say in PHP its going to be running under the Apache user. How do I go about configuring that?
I see, I usually do ruby development so the webserver is then usually running as my user on my development machine (obviously that is not the case in production).

In your case, then I would just change pg_hba to allow all local connections as shown by moe above. (I would not set any password though since that is normally not useful or necessary for local development).

     sudo -u postgres createuser -s `whoami`
Won't this create another user named "postgres"?

EDIT: No it won't:

     Ophelia ~ $ sudo -u postgres whoami
     postgres
     Ophelia ~ $ sudo -u postgres echo `whoami`
     rich
That seems straight out of The Unix Hater's Handbook.
The idea that commandline expansions like $VAR, `backtick` and wild*cards are done by the shell, before the program is invoked, is not particularly esoteric is it?
As for backup, pg_dump dbname > db.dump will do the dump, psql -f db.dump dbname will do the restore. There are, of course, far more complicated ways of doing it, including doing it in binary format, or data / schema only, or individual tables, but those are all a flag or two away.
Ok here is a guide I wrote for installing & setting up Postgres in Ubuntu. It's in Spanish but you will find your way around:

http://lobotuerto.com/blog/2009/07/20/como-instalar-postgres...

It covers instalation, setting up the postgres user (the _root_ you want), changing the authentication schema so you can use it for Rails dev (or something else), and finally how to install the Postgres gem for your Ruby.

Actually a bigger question is how are people migrating from their Mysql databases to postgresql. I'm quite surprised on the lack of a standard, production grade, defacto mysql2pg tool (and sql server as well).
pgdump to export as SQL, just pipe into psql to import.
There are some caveats about piping SQL into psql:

http://petereisentraut.blogspot.com.au/2010/03/running-sql-s...

One of the other nice things about Postgres is the pretty much annual release of a new version. 9.2 should apparently hit beta in the next week or so, which will bring some cool new features : http://archives.postgresql.org/pgsql-hackers/2012-05/msg0034... .
Are there any reasons not to use postgres, as a replacement for mysql?
If you have a DBA that knows MySQL extremely well and doesn't need to change. If you have a existing system running well, and the future roadmap of your development doesn't make staying with MySQL difficult.

I am totally a Postgres fan, but there are many sensible reasons not to upset the apple cart.

If you use multi-master replication, MySQL Cluster, or depend on properties of one of the alternative storage engines would be my big ones.
Hopefully PostgreSQL-XC might fix this lack of good multi-master replciation in a couple of years. PostgreSQL-XC 1.0 will be released soon.
I had no clue that Postgres supported LISTEN and NOTIFY. Granted, it's a new addition, but this is really slick:

http://www.postgresql.org/docs/9.1/static/sql-listen.html http://www.postgresql.org/docs/9.1/static/sql-notify.html

New addition?

listen and notify go back to at least 6.4 which came out 1998 ish http://www.postgresql.org/docs/6.4/static/sql-listen.html http://www.postgresql.org/docs/6.4/static/sql-notify.html

What might have changed is the implementation though. I seem to remember that some point in the past I was investigating listen/notify and the driver (libpq) was forcing you to handle LISTEN by polling (calling PQnotifies periodically) which doesn't really help compared to polling on your own.

This has not changed so far:

http://www.postgresql.org/docs/9.1/static/sql-listen.htm

states

> With the libpq library, the application issues LISTEN as an ordinary SQL command, and then must periodically call the function PQnotifies to find out whether any notification events have been received.

It might be possible for drivers working without libpq by talking the postgres protocol directly on the wire to get real asynchronous behavior, though I don't know anything about how this is being handled on the server right now (it might still be polling internally on the server end).

I'm not sure about long ago, but the recent version of libpq has NOTIFY working asynchronously (you can stick the connection file descriptor in a select(2) and you'll get woken up when a notify is available).
Hmm, pretty certain nothing has changed recently there either. At least as far back as 7.1 the documentation has remained the same about this.

http://www.postgresql.org/docs/7.1/static/libpq-notify.html

What has happened recently though is that more language bindings to libpq have started exposing the NOTIFY functionality in more convenient ways.

One of the bug fixes for Postgres95 Release 0.03 (Released 1995-07-21) is:

* the LISTEN/NOTIFY asynchronous notification mechanism now work

http://www.postgresql.org/docs/7.4/static/release-0-03.html

I'm not sure how much I like stuffing random functionality into the database... Looking at the docs: "and then must periodically call the function PQnotifies to find out whether any notification events have been received" - it's actually polling via an SQL connection - that means even more persistent connections to the DB, another timer in the application, more difficult connection sharing (two pools rather than one).

Without knowing much about how it works - why would I want to use this system rather than just ZMQ/RMQ/...?

You do not have to poll. You can wait on the socket until you get data and only then poll.
I quoted that part from the documentation - the way I understand it is that I can't detect if I have data (so I cannot "wait on the socket") in any other way than by polling via that function. Is that not correct?
LISTEN and NOTIFY are a great feature. We used them heavily in one system I worked on. As the project evolved though, we decided the best way to use them was to have clients to both our main message brokers and the postgres server, and translate between them. Largely this was to avoid overloading the pg server as a message broker also -- particularly because for our uses dbus was a much better alternative for local system message passing. Now that NOTIFYs officially have payload support, YMMV.
It's not exactly new, 7.4 was the oldest version I cared to check, but I think it goes back more :) http://www.postgresql.org/docs/7.4/static/sql-notify.html

A recent addition to NOTIFY is the ability for notifies to carry payloads (which makes them even more useful)

As the other posters have said, it has been around forever, but was rewritten to be much faster and support a payload in 9.0.
Can anyone point me at a HOW to use Postgres guide? I know my way around MySQL and SQL Server pretty well, but Postges is fairly new to me. I did one project where I migrated several websites from one server to another but I kind of fumbled my way through it. Would love to see a guide for getting started with Postgres for those who are already familiar with MySQL.
The official docs are fantastic. The newer PacktPub books are also pretty good http://www.packtpub.com/postgresql-90-high-performance/book and http://www.packtpub.com/postgresql-9-admin-cookbook
It should be said that the older books have never been very good. I have read probably all of them, none come close to the documentation on the website.
You can check the guide mentioned in the article: http://www.postgresguide.com/
Has slowness of SELECT COUNT() on large datasets been addressed in any way? Last time I checked it was responded with "it's slow because of how we do things here" and if you want to count records fast "you count them yourself" (not actual quotes from anyone, just tl;dr of some answers I've seen).
I kind of hate this "tl;dr" culture. I can explain the reason why this is never going to change (though it may get better with index scans) but I expect you'll just see a wall of text and decide not to read it. But if you never read long answers, you have no right to expect solutions to your problems or to understand anything. So I hope you'll read this, it may help.

PostgreSQL and most modern, ACID-compliant RDBMSes use MVCC instead of locks. MVCC has a lot of upsides, namely, you almost never need table-level locking for writes, but it ensures you need to look at the whole table to do COUNT. That's because MVCC is basically multiple parallel universes for data. What you see depends critically on which transaction you're in when you look.

For example, suppose you have a process that needs to know the number of users in some user table. You start your transaction, and then another process starts a transaction that goes through and deletes certain users. While this is happening, you need the count. In MVCC, deletion doesn't delete, it just marks rows with the transaction ID range in which they're visible. The rows that are being deleted by the other process are just being marked dead as of that process's transaction ID, but your transaction ID is below that one, so they're not dead to you. Later on, when the youngest transaction alive is older than the oldest transaction that can see these rows, PostgreSQL will actually expunge the data (VACUUM does this).

Because of MVCC, there is more than one legitimate answer the question of COUNT; potentially, one for each transaction in progress. The answer is changing constantly. People tend not to think in these terms; we tend to think, well the table has so many rows in it, right? Why don't you just increment the count when you write one? It's not true, because with ACID compliance, uncommitted transactions should not have visible effects until they commit and transactions in progress should not see anything vary during their operation. So there really are multiple right answers at any given moment. The expectation that SELECT COUNT(*) will be fast is built on the assumption that the database has some sort of master count of what rows are in the table it can just glance at. But it doesn't, and to have one would require removing MVCC altogether and using locks instead.

I'm not sure I buy your argument. It is certainly true that with MVCC "there is more than one legitimate answer the question of COUNT", but that's true for any query, not just COUNT. Given that we can maintain transactional correctness for the data, it's not at all clear to me why the same mechanisms cannot be used to maintain transactional correctness for the metadata.
Yes, but we're not surprised when those other queries have to read the table. For some reason it's surprising with COUNT. I maintain this is not a technical problem so much as an intuition problem.

Explain how you're going to maintain this metadata in more depth. If it can be done in an MVCC manner (i.e. without introducing locks) then it should be explored. How's it going to work?

I agree. Given count(star) is a common need you'd think there would be multiple count(star) results in the metadata for the table, each with a generation associated with it.
^ tl;dr no, it's still slow

sorry, I couldn't help myself :-)

I understand that it's semi-hard problem given MVCC but I could keep track of counts myself for each set of conditions and each table that I need. It's as simple as keeping count as record in some table, incrementing it in on insert, decrementing in on delete and adjusting on update if row begins or stops to satisfy conditions I want to count by. The only grudge I have with PostrgreSQL is that when confronted with this problem PostgreSQL fans respond with "We've got MVCC so it is supposed to be slow. Stop thinking it's supposed to be fast." not with "Hmm... Maybe we should introduce new facility similar to indexes where you could define what you want to count and the db will count by this conditions and provide results for you fast."

If you mean, "have other major database vendors, such as MySQL, become slower in most of the same ways", then "yes, and for the same reasons ;P"; the one place PostgreSQL could be better on that is that it can't use a covering index currently (which would let it get the count of a filtered query only with a scan of the index, without needing to read and validate the table rows), but that is being addressed in 9.2.
I basically find your sentiment accurate: databases with high concurrency support need to do a lot of work to do an accurate count(*). However, many that were not postgres supported index-only scans to do it. That doesn't change the algorithmic complexity of O(n) to grovel through the tuples, but it can have a large constant time difference.

No anymore, though....9.2 supports index only scans in many common cases.

Still, as you say, counting all your tuples repeatedly in a table is going to be much, much more expensive than maintaining the count on categories you care about up-front, paying the lock contention and update-costs as one goes in virtually any database that supports SMP.

If you want an approximate count you can do something like to get data for all your tables:

     SELECT S.nspname || '.' || relname, reltuples 
      FROM pg_class C,  pg_namespace S 
      WHERE C.relnamespace = S.oid 
      ORDER BY reltuples DESC
This is the estimate used by the query planner, so it's updated whenever a VACUUM occurs (not sure how often the autovacuum runs).
As often as it is needed, depending on your database settings.