Author: way0utwest

  • Database Design for Tracking Solar Production

    We had a solar system installed at our house this year. I’m excited to see how this performs, as our estimates and research shows this ought to be a good financial decision for us over time. While the hardware that came with the system includes some monitoring and reporting, I wanted to track things independently to be sure that I have the data. I know many of these companies might not be as prepared for an issue as I would like, and if they lose some of my historical data, I’m not sure they care.

    I decided to set up a small database, which will need an import process along with reporting and this is the first in a series of posts on how I’m addressing the database design. In this post, I’ll look at the initial tables I created.

    Estimated Production Table

    My system included some estimated levels of production for the year, and I will be able to record the actual levels each day. I decided to track these two sets of data separately for a couple reasons.

    First, the estimates are monthly, and they do not vary. While I could just stick this data in the same table, it’s a lot of wasted data. Not a lot of space, but still, I decided to be efficient here. The estimates I have are a total for each month, with the math done to give me a daily power level. I decided to create this table:

    CREATE TABLE [dbo].[SolarPowerEstimate](
         [TrackingKey] [int] IDENTITY(1,1) NOT NULL,
         [trackingmonth] [tinyint] NULL,
         [estimate_month] [numeric](6, 2) NULL,
         [estimate_daily] [numeric](4, 2) NULL,
      CONSTRAINT [SolarPowerPK] PRIMARY KEY CLUSTERED
    (
         [TrackingKey] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    This table has a PK just to keep things simple, and then I have a month number, which tracks for which month I have an estimate. There should only be 12 months in this table, as the estimate is supposed to repeat each year. I included the numeric values for the month and daily levels.

    The data in this table looks like this:

    2022-04-24 18_19_13-solartracking.sql - ARISTOTLE_SQL2017.way0utwest (ARISTOTLE_Steve (54))_ - Micro

    I can join this with my actual production to compare how well things are working.

    Actual Production

    For Actual production, there is a value for each day. As a result, I need a date and a numeric value. I decided to separate out the date into separate parts, as I can always combine those, but this is really a data warehouse structure for me and I want to quickly join this with my estimate. I also expect to do some reporting by month, so having the month separated out (and the year) is a quick way to join data without needing a function.

    CREATE TABLE   [dbo].[solarpoweractual](
         [TrackingKey] [int] IDENTITY(1,1) NOT NULL,
         [trackingyear] [smallint] NULL,
         [trackingmonth] [tinyint] NULL,
         [trackingday] [tinyint] NULL,
         [actual_daily] [numeric](10, 4) NULL,
      CONSTRAINT [SolarPowerActualPK] PRIMARY KEY CLUSTERED
    (
         [TrackingKey] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO

    This  table will be populated with numbers for the date parts and then the production value. Right now, I see data like this:

    2022-04-24 18_22_39-solartracking.sql - ARISTOTLE_SQL2017.way0utwest (ARISTOTLE_Steve (54))_ - Micro

    I’ll go over reporting and how I use this data in another post, but there is one more table I need for this system.

    Staging Imports

    I can download data daily, but I really don’t care about the flows of the data each day. The data is reported each 15 minutes, but that’s a bit granular for me. Instead, I want to download monthly data. If I do that, I get a row for each day of the month, but some days are 0 if they are in the future. The current day is also incomplete until the sun goes down, so I may need to update that data regularly.

    Rather then try to parse the data and build a complex ETL process, I’m aiming for an ELT, with a T that moves data from a staging table to my actual table with an upsert process.

    The csv I get from my monitoring system is a date and a numeric value, so I built a staging table like this:

    CREATE TABLE [dbo].[SolarStaging](
         [Time] [date] NOT NULL,
         [System_Production_Wh] [varchar](50) NOT NULL
    ) ON [PRIMARY]
    GO

    My aim here is to truncate this table, load the entire CSV, and then transform data as needed.

    Summary

    That’s the basics of my solar tracking database. I have a place to land new data, a table for the estimates I have for each month of the year, and then a table that is essentially a fact table of actual values.

    I’ll add more details on how I load data, as well as how to analyze the data over time.

  • Migrating a Large Database

    I have upgraded lots of SQL Servers from one version to the next, and for the most part, the process has been smooth. That’s not always the case, and there have been some long nights where the Operations staff had to scramble to fix things, script out old logins, call Microsoft support, and perform various data exports and imports to get a new instance running. I’ve been a part of quite a few of those teams.

    Most of my upgrades were with relatively small databases, at least small for that time period. However, I have upgraded a few “large” databases in the past. We had a 400GB database on SQL Server 6.5 in 1999 that was a challenge to move to SQL Server 7. I also upgraded an 800GB database in 2001 from 6.5 to 2000 for our Financial team, which involved a lot of stress.

    I haven’t upgraded a 1TB database, much less a 4TB one, but I know this can be very time-consuming to move all that data. Even with much faster hardware and networks these days, working with that much data can require a decent amount of downtime. That’s not very acceptable these days, especially for applications that are used by customers all around the world and all around the clock.

    I found an interesting upgrade story from a SaaS provider that runs PostgreSQL. I don’t use that platform, but I found the write-up of their process to be aligned with some of my experiences with SQL Server. They delayed upgrading an old version of PostgreSQL and then had the desire to move to as current a version as possible and delay future upgrades (again). I’ve certainly experienced that. Their goal was also to minimize downtime, as their customers are constantly connecting.

    The plan for the upgrade made sense to me. Use replication to move most data and then minimize downtime. That’s a technique that can work in SQL Server, though we’d be more likely to use log shipping to simulate this. They also trimmed and cleaned some data, removing the need to upgrade some of the tables. That’s something many of us might be able to do every year in some databases, especially for large logging tables where older data might rarely be read. I’d even think about moving that data to another database and using a synonym to access it if it were needed. That’s just a good idea for general DR planning.

    I also appreciated them creating a runbook and testing the process multiple times in staging. Their big takeaway here: practice over and over with a realistic workload. They created some problems for themselves by not using a real enough workload. That ought to be something your organization does on a regular basis to test your software and ensure new code performs well. Using the same process for upgrades is a bonus.

    Large upgrades are stressful and often they are “big bang” deployments where you can’t go back to the old system. Practice as much as you can, make sure you have backups, and then be ready to adapt to whatever challenges come up. Plan ahead, and be prepared for a long night. If you do, you’ll likely have success. If you don’t, I am fairly sure something will go wrong and you’ll regret not thinking ahead.

    Steve Jones

    Listen to the podcast at Libsyn, Stitcher, Spotify, or iTunes.

  • Daily Coping 27 Apr 2022

    I started to add a daily coping tip to the SQLServerCentral newsletter and to the Community Circle, which is helping me deal with the issues in the world. I’m adding my responses for each day here. All my coping tips are under this tag.

    Today’s tip is to spend less time sitting today, get up and move more often.

    The other day we did stretching and breathing. Today I’m going to do more walking. I am setting some reminders to take 5 minutes to walk a bit and move my body around other tasks. I might do 5 minutes of yoga a few times as well, maybe holding a few poses and just getting my heart pumping harder.

    2022-04-18 16_28_02-Calendar - steve.jones@red-gate.com - Outlook

    Somewhere in here I also need to get to the gym and lift a bit as well, but this will be a bit of movement.

  • Daily Coping 26 Apr 2022

    I started to add a daily coping tip to the SQLServerCentral newsletter and to the Community Circle, which is helping me deal with the issues in the world. I’m adding my responses for each day here. All my coping tips are under this tag.

    Today’s tip is to focus on eating a rainbow of vegetables.

    Today is my medium carb day, which means I have these meals:

    • yogurt with berries and nuts
    • fruit smoothie
    • ground turkey with rice and broccoli
    • fruit smoothie
    • turkey meatloaf with vegetables and quinoa

    I vary these slightly, but the general idea is the same. I’m going to aim to get a variety of vegetables today with different colors. I’ll add some tomatoes and yellow squash to lunch, and then skip the quinoa and use some corn and different colored peppers with meatloaf, adding some zucchini to the meatloaf.

    That’s a bit of a rainbow.