我已经看到了许多不同的方法来创建和填充数字表。但是,创建和填充一个的最佳方法是什么?从“最重要”到“最不重要”定义“最佳”:
用最佳索引创建的表 产生最快的行 用于创建和填充的简单代码
这是一些从网上获取的代码示例,以及对该问题的解答。
对于每种方法,我都修改了原始代码,因此每种方法都使用相同的表和列:NumbersTest和Number,具有10,000行或尽可能接近的行。另外,我提供了到原产地的链接。
方法1在这里是一种非常慢的循环方法,平均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从这里循环的速度要快得多, 平均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,其中 平均488.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这里是“半循环”的方法从这里 平均348.3毫秒(这是很难获得,因为在代码中间的“走出去”的好时机,有什么建议,将不胜感激) 跑了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这是Philip Kelley的回答中的一次INSERT, 平均92.7毫秒 最高去除了11次,这是毫秒数:80、96、96、93、110、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这里是来自Mladen Prajdic的单个INSERT, 平均82.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这里 平均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,这是最快的方法,代码也很简单。