What is the best way to create and populate a numbers table?

后端 未结 11 2522
悲&欢浪女
悲&欢浪女 2020-11-21 13:28

I\'ve seen many different ways to create and populate a numbers table. However, what is the best way to create and populate one? With \"best\" being defined from most to l

11条回答
  •  一整个雨季
    2020-11-21 13:53

    I know this thread is old and answered, but there is a way to squeeze a little extra performance out of Method 7:

    Instead of this (essentially method 7 but with some ease of use polish):

    DECLARE @BIT AS BIT = 0
    IF OBJECT_ID('tempdb..#TALLY') IS NOT NULL
      DROP TABLE #TALLY
    DECLARE @RunDate datetime
    SET @RunDate=GETDATE()
    SELECT TOP 10000 IDENTITY(int,1,1) AS Number
        INTO #TALLY
        FROM sys.objects s1       --use sys.columns if you don't get enough rows returned to generate all the numbers you need
        CROSS JOIN sys.objects s2 --use sys.co
    ALTER TABLE #TALLY ADD PRIMARY KEY(Number)
    PRINT CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))+' milliseconds'
    

    Try this:

    DECLARE @BIT AS BIT = 0
    IF OBJECT_ID('tempdb..#TALLY') IS NOT NULL
      DROP TABLE #TALLY
    DECLARE @RunDate datetime
    SET @RunDate=GETDATE()
    SELECT TOP 10000 IDENTITY(int,1,1) AS Number
        INTO #TALLY
        FROM        (SELECT @BIT [X] UNION ALL SELECT @BIT) [T2]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T4]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T8]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T16]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T32]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T64]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T128]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T256]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T512]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T1024]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T2048]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T4096]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T8192]
        CROSS JOIN  (SELECT @BIT [X] UNION ALL SELECT @BIT) [T16384]
    ALTER TABLE #TALLY ADD PRIMARY KEY(Number)
    PRINT CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))+' milliseconds'
    

    On my server this takes ~10 ms as opposed to the ~16-20 ms when selecting from sys.objects. It also has the added benefit of not being dependent on how many objects are in sys.objects. While it's pretty safe, it's technically a dependency and the other one goes faster anyway. I think the speed boost is down to using BITs if you change:

    DECLARE @BIT AS BIT = 0
    

    to:

    DECLARE @BIT AS BIGINT = 0
    

    It adds ~8-10 ms to the total time on my server. That said, when you scale up to 1,000,000 records BIT vs BIGINT doesn't appreciably affect my query anymore, but it still runs around ~680ms vs ~730ms from sys.objects.

提交回复
热议问题