Category: Blog

  • A Couple Quick GENERATE_SERIES Tests

    I had someone reach out about generate_series() recently, saying they hadn’t realized this was a new feature in SQL Server 2022. They were wondering if it was better than using a tally table.

    I didn’t want to do an exhaustive test, but I thought I’d take a minute and try a couple simple things just to see.

    A First Test

    The first thing was to just generate a million numbers. Rather than just get the numbers. I decided to use a quick DATEADD() to create a list of calendar dates. Here’s the code:

    SET STATISTICS IO ON;
    SET STATISTICS TIME ON;
    -- Create a Tally table with 1 million numbers
    WITH Tally (n)
    AS ( SELECT TOP (1000000)
                 ROW_NUMBER () OVER (ORDER BY
                                       (SELECT NULL)) AS Number
          FROM
            master.dbo.spt_values a
            CROSS JOIN master.dbo.spt_values b)
    SELECT DATEADD(DAY, n, GETDATE())
      FROM tally
    
    SELECT DATEADD( DAY, value, GETDATE()) FROM GENERATE_SERIES(1, 1000000, 1)

    Since this does read from tables, I ran it twice. The first time, the tally table took 243ms, so I re-ran it and saw this drop to 172ms. The results were consistent for Generate_series, which was 110ms.

    2025-02_0343

    A Second Test

    I grabbed Jeff Moden’s code for random numbers and adjusted a second query to use GENERATE_SERIES(). The code is below.
    
    SET STATISTICS IO ON;
    SET STATISTICS TIME ON;
    
    --===== Declare some obviously named variables
    DECLARE @NumberOfRows INT,
    @StartValue   INT,
    @EndValue     INT,
    @Range        INT
    ;
    --===== Preset the variables to known values
    SELECT @NumberOfRows = 1000000,
    @StartValue   = 400,
    @EndValue     = 500,
    @Range        = @EndValue - @StartValue + 1
    ;
    --===== Conditionally drop the test table to make reruns easier in SSMS
    IF OBJECT_ID('tempdb..#SomeTestTable','U') IS NOT NULL
    DROP TABLE #SomeTestTable
    ;
    --===== Create the test table with "random constrained" integers and floats
    -- within the parameters identified in the variables above.
    SELECT TOP (@NumberOfRows)
    SomeRandomInteger =  ABS(CHECKSUM(NEWID())) % @Range + @StartValue,
    SomeRandomFloat   = RAND(CHECKSUM(NEWID())) * @Range + @StartValue
    INTO #SomeTestTable
    FROM sys.all_columns ac1
    CROSS JOIN sys.all_columns ac2
    
    SELECT TOP (@NumberOfRows)
    SomeRandomInteger =  ABS(CHECKSUM(NEWID())) % @Range + @StartValue,
    SomeRandomFloat   = RAND(CHECKSUM(NEWID())) * @Range + @StartValue
    INTO #SomeTestTable2
    FROM GENERATE_SERIES(1, @NumberOfRows, 1)

    When I ran this, I see these results:

    2025-02_0344

    Execution times are close. Slightly faster with GENERATE_SERIES(), but fairly consistent across runs. In running this 10 times, there were 3 runs where the tally table was faster, and once just under 300ms. A few times the time was the same, but always within 15-16ms. Not sure that means much.

    This isn’t a really exhaustive test, and don’t take this as a recommendation either way for your code. Test how they both work in your system, and certainly think about the impact of storing a tally table vs. generating one on the fly vs the GENERATE_SERIES().

    However, it seems that GENERATE_SERIES() is worth looking at if you are on SQL Server 2022 or later.

  • What is Deferred Name Resolution?

    One interesting concept in SQL Server is Deferred Name Resolution. This is something many developers struggle with understanding how this works and where it works.

    In the Microsoft docs, there is a specific section in the CREATE TRIGGER docs that covers Deferred Name Resolution. This is a short section, and I’ve reproduced it below:

    SQL Server allows for Transact-SQL stored procedures, triggers, and batches to refer to tables that don’t exist at compile time. This ability is called deferred name resolution.

    I don’t know how batches are compiled, but procs and triggers are compiled for sure. What this statement says is that I can reference a table in a proc or trigger that doesn’t exist. When I create the trigger or proc, the reference is deferred at compile time and resolved at runtime.

    Let’s see how this works. I’ll run this code in SSMS, all at once. In this code, I create a database in one batch, switch to it in the next, and then create a proc in the third.

    CREATE DATABASE DNRTest
    GO
    USE DNRTest
    go
    CREATE PROCEDURE dnrproc
    AS
    SELECT * FROM sdfsfdsfs
    GO

    If we look in SSMS, this works.

    2025-02_0326

    In my database, I have only one object, the stored procedure.

    2025-02_0327

    However, if I execute this, it fails.

    2025-02_0328

    The table doesn’t exist, so the proc fails. However, I can not create the table and re-run the proc, and it works.

    2025-02_0329

    This is handy as I might create procs that reference temp tables, which don’t exist until they’re created. Often this happens in the proc, but if we were to try and resolve the reference at compile time, it would fail.

    This also works in triggers as I might often script a table and triggers that reference a second table. When I run that script, I don’t want to trigger creation to fail, so I defer the name resolution until the trigger fires. This way my scripts can be organized logically.

    This also works with functions, as seen below.

    2025-02_0330

  • Book Review: A Radical Enterprise

    I grabbed this book over the 2024 holiday season as it was on sale and recommended by the DevOps practitioners over at ITRevolution.

    A Radical Enterprise looks at a new way of building organizations, actually a few way, where the power and decisions are decentralized.

    I am pretty open to trying new things and experimenting, but I was very skeptical this would work in many places as I started this book and remain so after finishing it. I kept thinking this felt like a feel-good, kumbaya approach to running an organization. Giving responsibility, devolving it from management to individual teams and having them collaborate together and with other teams.

    While I am skeptical, there are some large organizations doing this, and the description says 8% of corporations do this, which I find hard to believe. In any case, a few of them are:

    • Haier – USD$38b in revenue
    • Morning Star – processing about 40% of the world’s tomato products
    • Buurtzorg: – over €427 million revenue
    • Nearsoft – $80mm consultancy
    • W. L. Gore & Associates – makers of Gore-Tex products, over US$3b in revenue

    Those are some impressive organizations. Maybe 8% isn’t wrong, but it feels high. I’ve worked in a few organizations, and all of them have a more central control organization. Even at Redgate, where I think we give a lot of autonomy to teams, I wouldn’t think we’re in the category of a radical organization.

    There are some principles to this idea, and some imperatives. The imperatives are:

    • Team autonomy – giving control to small groups in terms of how they practice and schedule work as well as allocate themselves.
    • Managerial devolution – trying to allow individuals or teams to manage themselves
    • Deficiency Gratification – gratifying our higher level needs. Not things we need, but we want and desire. I’m not sure I completely understand this.
    • Candid vulnerability – being open and transparent. Even for someone like me that is fairly open, this is asking a lot.

    Ultimately, I’ve worked with too many people who aren’t motivated, who don’t try and drive forward, who don’t want to make decisions, or who don’t want accountability. I think many of the people I’ve worked with wouldn’t thrive in this type of org and would get booted. Maybe that’s OK, and maybe this is only suited to some types of people.

    It’s an interesting idea, and I found myself fascinated and rooting for success, but always thinking this wouldn’t work in most places I’ve worked. Maybe all the places I’ve worked.

    Give it a try if you want a different way of thinking about work, and if it’s for you, maybe look for a job at one of these organizations.

  • Advice I Like: Investing and Growing Rich

    Investing small amounts of money over a long time works miracles, but no one wants to get rich slow.  – from Excellent Advice for Living

    This is incredible advice, and something my parents instilled in me at a young age. I’ve had mixed financial success here, but I do think about this in a different way.

    Learning new things and growing your career are things that happen slowly as well, but so many people don’t see the value of small things learned every day. Or managers don’t see the value of having employees learn constantly vs taking a week for a class.

    Note, they sometimes don’t even want to give you a week to learn.

    Whether you want to grow your finances or your career, regular investment is slow, but it pays incredible dividend over time. Learn, experiment, and practice your skills regularly. It works in music, in sports, and it also helps your career.

    I’ve been posting New Words on Fridays from a book I was reading, however, a friend thought they were a little depressing. They should be as they are obscure sorrows. I like them because they make me think.

    To counter-balance those, I’m adding in thoughts on advice, mostly from Kevin Kelley’s book. You can read all these posts under the advice tag.