Find the Best Time for Maintenance: Answers & Discussion

Your Query Exercise was to find the best time to take the database offline for maintenance – the time when we’ve got the least load. We kept this one pretty simple by looking at the data in just one table, and we didn’t hassle with time zones. We just wanted the 3 lowest-load hours, in this format:

  • Mondays, 1:00-1:59
  • Saturdays, 23:00-23:59
  • Sundays, 2:00-2:59

Kinda-Safe Technique:
Grouping by date_part

One way to do this is to use the built-in date_part function to group users by weekday and hour of their creation dates, like this:

And at first glance, that looks like it works:

It looks like late Sunday night, early Monday mornings are the best times:

  • Monday 00:00-00:59
  • Sunday 23:00-23:59
  • Monday 01:00-01:59

But…there’s a catch. This technique only works as long as our historical data is populated for every hour of every day. What if we’ve been taking the web servers down every Sunday at 16:00-17:00? There wouldn’t be any users created in that date range, and thus, no rows would show up in the result set for that query!

The Safer Technique:
generate a list of days/times first.

In pseudocode:

That way, if we have any weekday/hour combinations with no users created, we’ll still have rows for them in our result set. In Postgres, one option for this is the generate_series function, which we discussed in a recent Technique of the Week.

The generate_series function does take timestamp parameters, but that’s probably overkill for what we’re doing here. We just need:

  • weekdays: a set of rows 0 through 6
  • hours: a set of rows 0 through 23

So we’ll call generate_series twice:

Like the bus driver said, you see where I’m going with this:

It just so happens that there are 168 rows (7 days x 24 hours = 168), and our original grouping-by-datepart result set had 168 rows, so in this case, we already know we’re safe. However, let’s finish the exercise out because sooner or later, you’re gonna hit a result set where you need this technique.

I’ll use the query we wrote earlier as a CTE, and join to it:

And there you have it! Hope you enjoyed the exercise. There are certainly lots of ways to accomplish this – subqueries, generate_series with timestamps, and more.

Previous Post
Smart Postgres News and Techniques 2024 Vol 4
Next Post
Query Exercise: Find Tagged Questions Faster.

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.
You need to agree with the terms to proceed