Making PostgreSQL tick: New features in pg_cron
citusdata.com
citusdata.com
That said, I'm very happy to see more and more stuff coming from Citus. We're looking to split a few growing databases and a bunch of folks are excited to try Citus again now that the enterprise features have been open sourced.
If all of them matter but the order doesn't, you might be able to use aggregations like sum.
If the order matters but you don't need to see all of them, you might use aggregations like min and max.
You can refactor some of your logic into an aggregation function if your use cases isn't in the standard library. Often helpful if you have some core business logic that contains lots of if statements, and so is easier to write imperatively.
But I also wish the language were more ergonomic.
So is declarative something like “writing high level statements that postgres turns into more specific (imperative?) instructions”? And imperative being writing those specific “do this, then do this” yourself (although probably differently than how postgres does it under the hood).
So functions in the database can be written in this imperative language (or in SQL), and integrated into features like database triggers or called be clients (or, commonly, used to write pg_cron jobs).
And your understanding of the distinction between them is correct. Declarative describes what you want to do but not how you want to do it, and Postgres' query planner (or that any fully featured SQL database) will uses statistics it has recorded about your data and indexes you've created to optimize the execution of your query (decide how to do it). PgSQL can tell Postgres what to do and how, except in the places where you're writing declarative SQL statements (since it's a superset). Breaking things up into smaller units like that limits the scope the planner can optimize over, which may defeat or limit certain optimizations and you may end up with something less performant.
For some straightforward examples: if you write a min or max function with a FOR loop, you have written an O(n) implementation for something the query planner can sometimes do in O(1) using an index. If you write a sum function, you've written a sequential implementation of something the query planner may be able to parallelize.
When you doing things imperatively instead you are degrading performance to pretty much the same you could achieve with a piece of python or js operating on the data set pulled out of the database wholesale without using any fast database features.
Main trouble with imperative SQL code is that some people that are forced to do something in the database, don't really know why SQL exists and given the opportunity of writing imperative code they jump straight to it instead of solving the puzzle of understanding SQL declarative primitives and applying them to their problem. So the project ends up with slow, buggy imperative code in horrible syntax. When somebody needs to fix it later they first have to find the slow business logic ... database is not the first place one looks for it. Then understand ugly imperative code to figure out what it's doing, then actually solve the problem properly which takes time and thinking. Some queries I wrote in my jobs took me a day or two of thinking. Imperative versions would take 2 hours but would be orders of magnitude slower on medium sized data sets.
Cron job are not just about db updates, and once you have one cron job in Python, having them scattered among several language is not ideal.
I think I’m with you on this one
On the other hand, it's quite useful to have a pure SQL cron that cannot do everything, but can run safely in managed services or under a restricted database user. That's probably one of the reasons why practically every managed PostgreSQL service offers pg_cron. Doing more things, like running shell scripts, might limit its usefulness.
There is not much you can do with it that you could not via external infrastructure that connects to the database, except you don't need to set up external infrastructure that connects to the database. (and simpler systems are generally more secure)