理货方式计算未来30年的打印日期-为什么要在理货方式中添加主键约束?

时间:2019-05-09 15:54:16

标签: sql sql-server constraints sql-server-2014 primary-key

这是我用来在接下来的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”查询,结果表中没有任何变化。

我想知道我应该添加ALTER查询(不能问他)的原因是什么?目的是什么?我看到它正在添加一个主键约束,但是为什么要使用clustered(n)fillfactor=100

谢谢!

3 个答案:

答案 0 :(得分:2)

就我个人而言,我将采用另一种方法来创建统计表。我将其作为我系统上的视图。闪电般快速,您不必担心存储空间。这是我从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

答案 1 :(得分:2)

伊瑞

为简单起见,FILLFACTOR属性告诉SQL Server数据(构成索引)的页面百分比。如果这是一个永远不变的表(无需重建索引);将此值设置为100是有意义的,因为任何小于100的值都会减少每个数据页上可以存储的数据量的容量(尽管程度较小)。

从MS的嘴里;他们认为当“未来可能增长到指数”时,这一点很重要:

https://docs.microsoft.com/en-us/sql/relational-databases/indexes/specify-fill-factor-for-an-index?view=sql-server-2017

有关更多信息,请咨询:https://www.brentozar.com/archive/2013/04/five-things-about-fillfactor/

答案 2 :(得分:1)

在没有指定索引的情况下,SQL Server将在您每次查找值时扫描整个表。因此,例如,如果您运行以下内容......

 SELECT * FROM #Tally WHERE N = 858;

SQL Server会扫描整个表以获取一条记录,这并不是很有效。假设您有30个这样运行查询的进程。您最终会遇到各种阻塞问题。

如果添加了指定的索引,则同一查询将在不扫描整个表的情况下找到N,并返回结果。在表上进行查找将非常有效,并且您创建的架构将支持更大的并发性。

现在,对于您提供的查询...

select dateadd(day, t.N - 1, @tmpDate)
from #Tally t
where t.N - 1 <= DATEDIFF(day, @tmpDate, @endDate)

SQL Server可能仍会进行表扫描。因此,在这种情况下,聚集索引的存在并不会给您带来很多好处。

您有一个会话表(#Tally),其中每天有一条记录,并且每天使用30年。该查询将选择回... 30年之内的天。由于在这种情况下,SQL Server必须进行全面扫描以获取每个记录的数据,因此我看不到添加索引会为您带来很多好处。不能使用模式和示例中的查询。

N列是一个很好的自然键。我不确定添加它是否会造成伤害,但是如果您不这样做,我认为您不会损失任何东西。但是,如果您确实开始从表中查询值的子集(并且我并不是说整个记录集减去一到两个),则聚集索引肯定会增加好处。

索引由页面组成。页面可以存储一定数量的数据。通常,您希望在每个页面中尽可能多地打包数据。因此,SQL Server不必扫描太多页面即可找到您的数据。将每一页想像成一个抽屉。如果抽屉中有1件物品,则需要500个抽屉才能存储500件物品。如果要查找20个项目,则必须打开20个抽屉。如果每个抽屉有100个物品,则您最多只能打开5个抽屉和至少1个抽屉。说FILLFACTOR equals 100意味着您没有在页面(抽屉)中留出任何空间;您将其完全填满。对于数据递增的字段,通常将填充因子设置为100是最佳做法,因为您永远不会在索引中间添加数据,而只会在末尾添加数据。因此,您不需要在索引的现有页面中留出空间来存储新数据。