sql >> データベース >  >> RDS >> Sqlserver

数値テーブルを作成してデータを入力するための最良の方法は何ですか?

    これは、Webとこの質問への回答から得られたいくつかのコード例です。

    各メソッドについて、元のコードを変更して、それぞれが同じテーブルと列を使用するようにしました。NumbersTestとNumberで、10,000行または可能な限りそれに近いものです。また、出身地へのリンクを提供しました。

    方法1 これは、ここからの非常に遅いループ方法です
    avg 13.01秒
    最高で3回削除されました。これは秒単位の時間です:12.42、13.60

    DROP TABLE NumbersTest
    DECLARE @RunDate datetime
    SET @RunDate=GETDATE()
    CREATE TABLE NumbersTest(Number INT IDENTITY(1,1)) 
    SET NOCOUNT ON
    WHILE COALESCE(SCOPE_IDENTITY(), 0) < 100000
    BEGIN 
        INSERT dbo.NumbersTest DEFAULT VALUES 
    END
    SET NOCOUNT OFF
    -- Add a primary key/clustered index to the numbers table
    ALTER TABLE NumbersTest ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
    PRINT CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE())/1000.0)+' seconds'
    SELECT COUNT(*) FROM NumbersTest
    

    方法2 これは、ここからはるかに高速なループです
    avg 1.1658秒
    最高で11回削除されました。これは秒単位の時間です:1.117、1.140、1.203、1.170、1.173、1.156、1.203、1.153、1.173、 1.170

    DROP TABLE NumbersTest
    DECLARE @RunDate datetime
    SET @RunDate=GETDATE()
    CREATE TABLE NumbersTest (Number INT NOT NULL);
    DECLARE @i INT;
    SELECT @i = 1;
    SET NOCOUNT ON
    WHILE @i <= 10000
    BEGIN
        INSERT INTO dbo.NumbersTest(Number) VALUES (@i);
        SELECT @i = @i + 1;
    END;
    SET NOCOUNT OFF
    ALTER TABLE NumbersTest ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
    PRINT CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE())/1000.0)+' seconds'
    SELECT COUNT(*) FROM NumbersTest
    

    方法3 これは、ここからのコードに基づく単一のINSERTです
    avg488.6ミリ秒
    最も高い11回削除されました。これはミリ秒単位の時間です:686、673、623、686,343,343,376,360,343,453

    DROP TABLE NumbersTest
    DECLARE @RunDate datetime
    SET @RunDate=GETDATE()
    CREATE TABLE NumbersTest (Number  int  not null)  
    ;WITH Nums(Number) AS
    (SELECT 1 AS Number
     UNION ALL
     SELECT Number+1 FROM Nums where Number<10000
    )
    insert into NumbersTest(Number)
        select Number from Nums option(maxrecursion 10000)
    ALTER TABLE NumbersTest ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
    PRINT CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))+' milliseconds'
    SELECT COUNT(*) FROM NumbersTest
    

    方法4 これは、hereavg 348.3ミリ秒からの「セミループ」メソッドです(コードの途中に「GO」があるため、適切なタイミングを取得するのは困難でした。提案をいただければ幸いです)
    11回実行され、最も高く削除されました。ミリ秒単位の時間は次のとおりです:356、360、283、346、360、376、326、373、330、373

    DROP TABLE NumbersTest
    DROP TABLE #RunDate
    CREATE TABLE #RunDate (RunDate datetime)
    INSERT INTO #RunDate VALUES(GETDATE())
    CREATE TABLE NumbersTest (Number int NOT NULL);
    INSERT NumbersTest values (1);
    GO --required
    INSERT NumbersTest SELECT Number + (SELECT COUNT(*) FROM NumbersTest) FROM NumbersTest
    GO 14 --will create 16384 total rows
    ALTER TABLE NumbersTest ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
    SELECT CONVERT(varchar(20),datediff(ms,RunDate,GETDATE()))+' milliseconds' FROM #RunDate
    SELECT COUNT(*) FROM NumbersTest
    

    方法5 これは、PhilipKelleyの回答からの単一のINSERTです。
    avg 92.7ミリ秒
    実行された回数は11回で最も高く、ミリ秒単位の回数です:80、96、96、93、110、110、80、76、93、 93

    DROP TABLE NumbersTest
    DECLARE @RunDate datetime
    SET @RunDate=GETDATE()
    CREATE TABLE NumbersTest (Number  int  not null)  
    ;WITH
      Pass0 as (select 1 as C union all select 1), --2 rows
      Pass1 as (select 1 as C from Pass0 as A, Pass0 as B),--4 rows
      Pass2 as (select 1 as C from Pass1 as A, Pass1 as B),--16 rows
      Pass3 as (select 1 as C from Pass2 as A, Pass2 as B),--256 rows
      Pass4 as (select 1 as C from Pass3 as A, Pass3 as B),--65536 rows
      --I removed Pass5, since I'm only populating the Numbers table to 10,000
      Tally as (select row_number() over(order by C) as Number from Pass4)
    INSERT NumbersTest
            (Number)
        SELECT Number
            FROM Tally
            WHERE Number <= 10000
    ALTER TABLE NumbersTest ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
    PRINT CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))+' milliseconds'
    SELECT COUNT(*) FROM NumbersTest
    

    方法6 これがMladenPrajdicの回答からの単一のINSERTです
    avg82.3ミリ秒
    実行された回数は最も高く11回削除されました。これはミリ秒単位の時間です:80、80、93、76、93、63、93、76、93、 76

    DROP TABLE NumbersTest
    DECLARE @RunDate datetime
    SET @RunDate=GETDATE()
    CREATE TABLE NumbersTest (Number  int  not null)  
    INSERT INTO NumbersTest(Number)
    SELECT TOP 10000 row_number() over(order by t1.number) as N
    FROM master..spt_values t1 
        CROSS JOIN master..spt_values t2
    ALTER TABLE NumbersTest ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number);
    PRINT CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))+' milliseconds'
    SELECT COUNT(*) FROM NumbersTest
    

    方法7 これは、ここからのコードに基づく単一のINSERTです。
    avg 56.3ミリ秒
    実行された回数は11回で最も高く、ミリ秒単位の回数です:63、50、63、46、60、63、63、46、 63、46

    DROP TABLE NumbersTest
    DECLARE @RunDate datetime
    SET @RunDate=GETDATE()
    SELECT TOP 10000 IDENTITY(int,1,1) AS Number
        INTO NumbersTest
        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.columns if you don't get enough rows returned to generate all the numbers you need
    ALTER TABLE NumbersTest ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
    PRINT CONVERT(varchar(20),datediff(ms,@RunDate,GETDATE()))+' milliseconds'
    SELECT COUNT(*) FROM NumbersTest
    

    これらすべてのメソッドを検討した後、私はメソッド7が本当に気に入っています。これは最速で、コードもかなり単純です。



    1. jsonフィールドタイプpostgresqlでnull値をクエリする方法は?

    2. mysql_fetch_assoc():指定された引数はphpの有効なMySQL結果リソースではありません

    3. 複合キーを使用したWHERE_INクエリ?

    4. MariaDBでMINUS演算子を使用するときのエラー1064(42000)を修正しました