A read query can write to disk: a Postgres story
mutuallyhuman.com
mutuallyhuman.com
Well they don't, and as soon as the product goes live and the amount of data slightly grows, the performance degrades exponentially.
* Never count on cloud databases to replace a DBA work.
* Don't take ORM optimizations for granted. They all suck at one point or another.
* If you can't afford an FTE, take short professional gigs from time to time to fix and boost performance.
I've been bitten many a time by this.
I'd even go as far to say if you don't know how to write SQL that does the same thing your ORM framework is doing, you're setting yourself up for a lot of pain later when you do something non-trivial.
Sure, its nice being able to say `ThisPost.authors.sort(DESC, 'postCount').where('active = true').select('name', 'avatarUrl', 'postCount')` anywhere in your codebase, but you know have spread knowledge of how to sort, filter; what attributes there are, what their relations are and so on, throughout your codebase.
Or, more on-topic: you know have spread knowledge about what can be fetched optimized, and what will cause performance pain, throughout your code. Suddenly some view-template, or completely unrelated validation, can now cause your database to go down.
Rails' activerecord is especially cumbersome in this: it offers "sharp knives"[0] but hardly any tooling to protect yourself (or that new intern) from leaving all those sharp knives lying around. A "has_and_belongs_to :users" and a ".where(users: { status: 'active', comment_count: '>10' }" is just two lines. But they will haunt you forever and probably will bring your database down if you have any load.
Cloud databases are a very easy option. But Postgres is 1.3 million lines of code, and on top of that you add the complexity of the cloud vendor's environment, choices, and custom code. It may be easy, but it's definitely not simple.
Automation and auto-tuning is kind of the whole value proposition of managed services, isn't it?
Number of Connections * work_mem is usually going to eat up the biggest chunk of your PostgreSQL's memory. AFAIK, the configuration is extremely coarse. There's no way for example to say: I want all the connections from username "myapp" to have 10MB and those from user "reporting" to have 100MB. And it can't be adjusted on the fly, per query.
Being able to set aside 200GB of memory to be used, as needed, by all connections (maybe with _some_ limits to prevent an accident), would solve a lot of problems (and introduce a bunch of them, I know).
Since they're on RDS, I can't help but point out that I've seen DB queries on baremetal operate orders of magnitude faster. 10 minute to 1 second type thing. I couldn't help but wonder if they'd even notice the disk-based sorting on a proper (yes, I said it) setup.
(1) https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Serv...
Managed databases in the cloud are a bit like ORMs: they significantly reduce the amount of knowledge needed 99% of the time. Sadly, when the 1% of the time hits this also means that nobody on the team has built up the DBA skills required for the big hairy problem. I see this pattern repeated all the time when consulting for startups that just had their first real traction and now the magic database box is no longer working as before.
But I don't see this model much. I mostly hear of companies struggling to develop internal expertise or going without.
Why?
It does exist (I'm one of them), and it's much more common on expensive databases like Microsoft SQL Server and Oracle. With free databases, it's relatively inexpensive to throw more hardware at the problem. When licensing costs $2,000 USD per CPU core or higher, there's much more incentive for companies to bring an expert in quickly to get hardware costs under control.
Managers don't like paying for optimization consultants, but it's the easiest way to both improve current performance and scale a master.
Note that Oracle positions MySQL as a replacement for SQL Server, as "moderate-performance databases." :)
Source: DBA.
https://metrixdata360.com/pricing-series/1500-price-increase...
I've pretty much completely changed careers now, but I found that this model did work well. It involved a lot of constant research and occasionally a huge amount of stress, but I loved it!
I got you fam: https://ottertune.com/
You have bought your 1000 hps car and are driving it as-is since you left the car dealer's parking place. Nobody told you to release the hand brakes.
I call this the Kubernetes effect. 99% of the time, people think it's easy. Then the 1% hits and they have to completely rebuild it from the ground up. For us it was cluster certificate expiration and etcd corruption, and some other problems we couldn't ever pin down.
The other effect (which I'm sure has a name) is when they depend on it for a long time, but then a problem starts to occur, and because they can't figure out a way to solve it, they move to a completely different tech ("We had problems with updating our shards so we moved to a different database") and encounter a whole new problem and repeat the cycle.
It's the amount of memory a connection has to do work per sorting/hashing operation. https://www.postgresql.org/docs/12/runtime-config-resource.h...
> There's no way for example to say: I want all the connections from username "myapp" to have 10MB and those from user "reporting" to have 100MB.
Yes, you can with
`ALTER ROLE myapp SET work_mem TO '10mb';`
and
`ALTER ROLE reporting SET work_mem TO '100mb';
Some days it's nice to have a lucky 10k problem (https://xkcd.com/1053) in place of a c10k problem (http://www.kegel.com/c10k.html). Thanks.
Sure it can:
SET LOCAL work_mem = '256MB';
SELECT * FROM …This is simplified explanation, but the point is the process executing a read query is often best positioned to do this maintenance work. This decision trades off a little latency for throughput.
Oracle also has two init.ora parameters, SORT_AREA_SIZE and SORT_AREA_RETAINED_SIZE, that are similar to the WORK_MEM mentioned in the subject article.
As far as I know, SORT_AREA_SIZE is global, and differing values cannot be assigned to roles.
https://dev.mysql.com/doc/refman/8.0/en/internal-temporary-t...
> Furthermore, the entire output is accumulated in temporary storage (which might be either in main memory or on disk, depending on various compile-time and run-time settings) which can mean that a lot of temporary storage is required to complete the query.
It also will sometimes create an index during a query. https://www.sqlite.org/tempfiles.html mentions this under "Transient Indices".
The default work_mem setting for Postgres has historically been very low. It's fine for reading single rows from a single table using an index, but as soon as you put a few joins in there it's not adequate. It should be one of the first steps of setting up Postgres to increase this limit.