Introducing Crunchy Data Warehouse: A next-generation Postgres-native data warehouse. Crunchy Data Warehouse Learn more

Latest posts from David Christensen

  • Building PostgreSQL Extensions: Dropping Extensions and Cleanup

    David Christensen

    I recently created a Postgres extension which utilizes the pg_cron extension to schedule recurring activities using the cron.schedule(). Everything worked great. The only problem was when I dropped my extension, it left the cron job scheduled, which resulted in regular errors:

    2024-04-06 16:00:00.026 EST [1548187] LOG:  cron job 2 starting: SELECT bridge_stats.update_stats('55 minutes', false)
    2024-04-06 16:00:00.047 EST [1580698] ERROR:  schema "bridge_stats" does not exist at character 8
    2024-04-06 16:00:00.047 EST [1580698] STATEMENT:  SELECT bridge_stats.update_stats('55 minutes', false)
    
    Read More
  • Tuple shuffling: Postgres CTEs for Moving and Deleting Table Data

    David Christensen

    Recently we published an article about some of the best sql subquery tools and we were talking about all the cool things you can do with CTEs. One thing that doesn’t get mentioned near enough is the use of CTEs to do work in your database moving things around. Did you know you can use CTEs for tuple shuffling? Using CTEs to update, delete, and insert data can be extremely efficient and safe for your Postgres database.

    PostgreSQL 15 included the MERGE

    Read More
  • Postgres Data Flow

    David Christensen

    At Crunchy we talk a lot about memory, shared buffers, and cache hit ratios. Even our new playground tutorials can help users learn about memory usage. The gist of many of those conversations is that you want to have most of your frequently accessed data in the memory pool closest to the database, the shared buffer cache.

    There's a lot more to the data flow of an application using Postgres than that. There could be application-level poolers and Redis caches in front of the database. Even on the database server, data exists at multiple layers, including the kernel and various on-disk caches. So for those of you that like to know the whole story, this post pulls together the full data flow for Postgres reads and writes, stem-to-stern.

    Application Server

    Read More
  • Postgres Locking: When is it Concerning?

    David Christensen

    When using monitoring tools like PgMonitor or pganalyze, Crunchy clients will often ask me about high numbers of locks and when to worry. Like most engineering-related questions, the answer is: "it depends".

    In this post, I will provide a little more information about locks, how they are used in PostgreSQL, and what things to look for to spot problems vs high usage.

    PostgreSQL uses locks in all parts of its operation to serialize or share access to key data. This can come in the form of two basic types of locks: shared or exclusive.

    • Shared locks

    Read More
  • Postgres Query Optimization: LEFT JOIN vs UNION ALL

    David Christensen

    Introduction

    The PostgreSQL optimizer is an amazing thing, getting only more amazing with each release. It is able to take information about your data definitions, your data distribution, constraints, and the specific queries and come up with the generally most efficient way to return the results of that query.

    Since SQL is a declarative language, we're explicitly giving up defining how

    Read More
  • 6 min read

    Devious SQL: Dynamic DDL in PostgreSQL

    David Christensen

    Supporting PostgreSQL DBAs is an important part of daily life here at Crunchy Data. I’ve recently run across a few use cases where utility queries based on the current state of the database are needed. A simple example could be where you have a table that is the target of logical replication and the id

    Read More
  • 8 min read

    Devious SQL: Message Queuing Using Native PostgreSQL

    David Christensen

    An interesting question came up on the #postgresql IRC channel about how to use native PostgreSQL features to handle queuing behavior. There are existing solutions for queuing, both in PostgreSQL, with the venerable pgq project, or dedicated message queues like RabbitMQ, Kafka, etc. I wanted to explore what could be done with native Postgres primitives and I thought this warranted an entry in my Devious SQL series

    Read More
  • Insert-Only Tables and Autovacuum Issues Prior to PostgreSQL 13

    David Christensen

    Generally, one appreciates new features of PostgreSQL on the release date after anxious inspection of the release notes or having skimmed through the git logs. Every once in a while, particularly when dealing with an older version of PostgreSQL, you will discover a feature that didn't get the necessary fanfare in order to come to your attention, but when you discover it, you're all the happier for it.

    I recently ran into an issue with some strange performance issues on a client's

    Read More
  • 6 min read

    Devious SQL: Run the Same Query Against Tables With Differing Columns

    David Christensen

    We spend time day in, day out, answering the questions that matter and coming up with solutions that make the most sense. However, sometimes a question comes up that is just so darn…interesting that even if there are sensible solutions or workarounds, it still seems like a challenge just to take the request literally. Thus was born this blog series, Devious SQL.

    Devious: "longer and less direct than the most straightforward way."

    The inaugural question

    Read More
  • 10 min read

    Simulating UPDATE or DELETE with LIMIT in Postgres: CTEs to The Rescue!

    David Christensen

    There have certainly been times when using PostgreSQL, that I’ve yearned for an UPDATE or DELETE statement with a LIMIT feature. While the SQL standard itself has no say in the matter as of SQL:2016, there are definite cases of existing SQL database dialects that support this.

    Sadly, if you try to do something like this in PostgreSQL, this is the result:

    ERROR:  syntax error at or near "LIMIT"
    LINE 1: DELETE FROM big_table LIMIT 10000;
                                  ^
    
    Read More