If we have an existing database, there is a wealth of statistical information at our fingertips. The first query we ran gave us a slightly inflated count of PostgreSQL replicas. For each replica, data must be transferred from the database to another server. This data is based on PostgreSQL WAL output, and these files are 16 MB each. A busy server can produce more than ten of these per second, so we multiply the count of streams by 160 to produce an aggressive amount of network overhead used by database replicas. As usual, this may be overzealous; it's always best to observe an actual system to measure maximum WAL segments generated during heavy write loads.
In PostgreSQL 9.2 and higher, database replicas can stream from other database replicas. This means network traffic can be distributed better among streaming clients, reducing network bandwidth pressure on production systems. PostgreSQL 9.2 and greater also allow direct backup of streaming replicas. This means one or two replicas may be the most the production database ever needs to supply with WAL traffic.
For the next set of numbers, we need to know how much data the database connections commonly retrieve. PostgreSQL tracks the number of table rows fetched, but it's a cumulative total. By waiting until a busy time of day and asking the database how many rows have been fetched before and after a one-second wait, we know how many rows are fetched per second.
However, we still don't know how many bytes these rows consume. A good estimate of this is 100 bytes per row. Then, we only have to multiply the number of rows by 100 to find the amount of bandwidth we would need. So why do we divide by 10,000? What's 10,000 multiplied by 100? One million. On dividing by 10,000, we produce the number of megabytes per second those tuple fetches probably used.
If an average of 100 bytes per row isn't good enough, we can connect to one of our primary databases and calculate the average tuple size. Use the query in the following code snippet:
SELECT sum(pg_relation_size(oid)) / sum(reltuples)
FROM pg_class;
By adding the amount of streaming traffic to the amount of connection traffic, we have a good, if slightly inflated, idea of how much bandwidth the server needs.
Without a working database to go by, we need to use a few guesses instead. Luckily, the number of streams for a reliable database infrastructure starts at two: one for a live standby, and one for an off-site archive. Each additional desired mirror should increase this total. Again, we multiply the number of streams by 160 to obtain the maximum MB/s that all these replicas are likely to require.
The amount of bandwidth client connections use is slightly harder to estimate. However, if we worked through previous chapter sections, we have a CPU estimate, which also tells us the maximum number of database clients the server can reliably support. If we take that value and multiply by five, that provides a rough value in MB/s as well.
Again, we just add those two totals together, and we know the minimum speed of our network.
Finally, we multiply the final tally by two to account for any unknown maintenance, backup, and filesystem synchronization overhead.