打印未来 30 年天数的 Tally 方法 - 为什么要在 Tally 中添加主键约束?
Tally approach to print days of next 30 years - why to add primary key constraint to tally?
这是我用来打印未来 30 年所有天数的查询。
SELECT TOP 11000 --number of days for 30 years
IDENTITY(INT,1,1) AS N
INTO #Tally
FROM Master.dbo.SysColumns sc1,
Master.dbo.SysColumns sc2
declare @endDate datetime = '2049-01-01'
,@tmpDate datetime = '2019-01-01'
select dateadd(day, t.N - 1, @tmpDate)
from #Tally t
where t.N - 1 <= DATEDIFF(day, @tmpDate, @endDate)
它运行良好。但是,SQL 专家建议我在我创建 #Tally 的第一部分的正下方添加这些查询。
ALTER TABLE #Tally
ADD CONSTRAINT PK_Tally_N
PRIMARY KEY CLUSTERED (N) WITH FILLFACTOR = 100
如果我运行 select * from #Tally
上面的"ALTER"查询,结果没有变化table.
我想知道我应该添加 ALTER 查询的原因是什么(不能问他)?这样做的目的是什么?我看到它正在添加主键约束,但为什么要使用 clustered(n)
和 fillfactor=100
?
谢谢!
就我个人而言,我会采用不同的方法来创建计数 table。我把它作为我系统上的一个视图。它快如闪电,您永远不必担心存储问题。这是我从 Jeff Moden 那里学到的技术,他是从 Itzik Ben-Gan 那里学到的。如果您很容易需要超过 10,000 行,则可以将其扩展为更多行。
create View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
在没有指定索引的情况下,SQL 服务器会在您每次查找值时扫描整个 table。因此,例如,如果您 运行 以下....
SELECT * FROM #Tally WHERE N = 858;
SQL 服务器将扫描整个 table 以获得那条记录,这不是非常有效。假设您有 30 个这样的进程 运行 查询。你最终会遇到各种阻塞问题。
如果您添加了指定的索引,相同的查询将找到 N 而无需扫描整个 table 和 return 结果。 table 上的查找会很高效,并且您创建的模式会支持更高的并发性。
现在,对于您提供的查询...
select dateadd(day, t.N - 1, @tmpDate)
from #Tally t
where t.N - 1 <= DATEDIFF(day, @tmpDate, @endDate)
SQL 服务器很可能只是进行 table 扫描。因此,在这种情况下,聚集索引的存在确实不会给您带来很多好处。
您有一个会话 table (#Tally),每天有一条记录,并且有 30 年的天数。查询选择返回... 30 年的天数。在这种情况下,由于 SQL 服务器必须进行全面扫描才能获取每条记录的数据,因此我认为添加索引不会给您带来多大好处。不适用于您示例中的模式和查询。
N 列是一个很好的自然键。我不确定添加它会不会有什么坏处,但我认为如果不添加它不会有任何损失。但是,如果您确实开始从 table 中查询值的子集(我不是指整个记录集减去一两个记录),聚簇索引肯定会增加好处。
索引由页面组成。页面可以存储一定量的数据。您通常希望在每个页面中打包尽可能多的数据 with-in。因此,SQL 服务器不必扫描太多页面即可找到您的数据。把每一页想象成一个抽屉。如果抽屉里有 1 件物品,则需要 500 个抽屉才能存储 500 件物品。如果你想找到 20 件物品,你必须打开 20 个抽屉。如果每个抽屉有 100 个物品,您最多需要打开 5 个抽屉,至少打开 1 个抽屉。说 FILLFACTOR equals 100
意味着您不会在页面(抽屉)中留下任何 space;你完全填满了它。对于数据递增的字段,使用 100 的填充因子是一般的最佳做法,因为您永远不会在索引的中间添加数据,只会将其添加到末尾。因此,您不需要 space 在索引的现有页面中获取新数据。
埃雷,
为了简单起见,FILLFACTOR 属性 告诉 SQL 服务器有多少百分比的页面(构成索引)填充了数据。如果这是一个永远不会改变的table(不需要重建索引);将此值设置为 100 是有意义的,因为任何小于 100 的值都会减少每个数据页上可以存储的数据量的容量(尽管程度很小)。
出自MS之口;当 "future growth to an index is likely":
时,他们认为这很重要
更多信息请咨询:https://www.brentozar.com/archive/2013/04/five-things-about-fillfactor/
这是我用来打印未来 30 年所有天数的查询。
SELECT TOP 11000 --number of days for 30 years
IDENTITY(INT,1,1) AS N
INTO #Tally
FROM Master.dbo.SysColumns sc1,
Master.dbo.SysColumns sc2
declare @endDate datetime = '2049-01-01'
,@tmpDate datetime = '2019-01-01'
select dateadd(day, t.N - 1, @tmpDate)
from #Tally t
where t.N - 1 <= DATEDIFF(day, @tmpDate, @endDate)
它运行良好。但是,SQL 专家建议我在我创建 #Tally 的第一部分的正下方添加这些查询。
ALTER TABLE #Tally
ADD CONSTRAINT PK_Tally_N
PRIMARY KEY CLUSTERED (N) WITH FILLFACTOR = 100
如果我运行 select * from #Tally
上面的"ALTER"查询,结果没有变化table.
我想知道我应该添加 ALTER 查询的原因是什么(不能问他)?这样做的目的是什么?我看到它正在添加主键约束,但为什么要使用 clustered(n)
和 fillfactor=100
?
谢谢!
就我个人而言,我会采用不同的方法来创建计数 table。我把它作为我系统上的一个视图。它快如闪电,您永远不必担心存储问题。这是我从 Jeff Moden 那里学到的技术,他是从 Itzik Ben-Gan 那里学到的。如果您很容易需要超过 10,000 行,则可以将其扩展为更多行。
create View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
在没有指定索引的情况下,SQL 服务器会在您每次查找值时扫描整个 table。因此,例如,如果您 运行 以下....
SELECT * FROM #Tally WHERE N = 858;
SQL 服务器将扫描整个 table 以获得那条记录,这不是非常有效。假设您有 30 个这样的进程 运行 查询。你最终会遇到各种阻塞问题。
如果您添加了指定的索引,相同的查询将找到 N 而无需扫描整个 table 和 return 结果。 table 上的查找会很高效,并且您创建的模式会支持更高的并发性。
现在,对于您提供的查询...
select dateadd(day, t.N - 1, @tmpDate)
from #Tally t
where t.N - 1 <= DATEDIFF(day, @tmpDate, @endDate)
SQL 服务器很可能只是进行 table 扫描。因此,在这种情况下,聚集索引的存在确实不会给您带来很多好处。
您有一个会话 table (#Tally),每天有一条记录,并且有 30 年的天数。查询选择返回... 30 年的天数。在这种情况下,由于 SQL 服务器必须进行全面扫描才能获取每条记录的数据,因此我认为添加索引不会给您带来多大好处。不适用于您示例中的模式和查询。
N 列是一个很好的自然键。我不确定添加它会不会有什么坏处,但我认为如果不添加它不会有任何损失。但是,如果您确实开始从 table 中查询值的子集(我不是指整个记录集减去一两个记录),聚簇索引肯定会增加好处。
索引由页面组成。页面可以存储一定量的数据。您通常希望在每个页面中打包尽可能多的数据 with-in。因此,SQL 服务器不必扫描太多页面即可找到您的数据。把每一页想象成一个抽屉。如果抽屉里有 1 件物品,则需要 500 个抽屉才能存储 500 件物品。如果你想找到 20 件物品,你必须打开 20 个抽屉。如果每个抽屉有 100 个物品,您最多需要打开 5 个抽屉,至少打开 1 个抽屉。说 FILLFACTOR equals 100
意味着您不会在页面(抽屉)中留下任何 space;你完全填满了它。对于数据递增的字段,使用 100 的填充因子是一般的最佳做法,因为您永远不会在索引的中间添加数据,只会将其添加到末尾。因此,您不需要 space 在索引的现有页面中获取新数据。
埃雷,
为了简单起见,FILLFACTOR 属性 告诉 SQL 服务器有多少百分比的页面(构成索引)填充了数据。如果这是一个永远不会改变的table(不需要重建索引);将此值设置为 100 是有意义的,因为任何小于 100 的值都会减少每个数据页上可以存储的数据量的容量(尽管程度很小)。
出自MS之口;当 "future growth to an index is likely":
时,他们认为这很重要更多信息请咨询:https://www.brentozar.com/archive/2013/04/five-things-about-fillfactor/