表之间的外键是否应该链接到自然键或代理键是否有最佳实践?我真正找到的唯一讨论(除非我的 google-fu 缺失)是Jack Douglas 在这个问题中的回答,他的推理对我来说似乎是合理的。我知道除了规则改变之外的讨论,但这在任何情况下都需要考虑。
提出这个问题的主要原因是我有一个遗留应用程序,它使用带有自然键的 FK,但是开发人员强烈推动转向 OR/M(在我们的例子中是 NHibernate),并且一个 fork 已经产生了一些破坏性更改,因此我希望使用自然键将它们推回正轨,或者移动旧应用程序以使用 FK 的代理键。我的直觉告诉我要恢复原始的 FK,但老实说,我不确定这是否真的是正确的道路。
我们的大多数表都已经定义了代理键和自然键(尽管是唯一约束和 PK),因此在这种情况下,必须添加额外的列对我们来说不是问题。我们使用的是 SQL Server 2008,但我希望这对于任何数据库都足够通用。
SQL Server 是否有任何简单的方法来获取有关给定查询在执行过程中取出多少(以及可能是什么类型)锁的指标?
基本原理...
我正在重写一个相当讨厌的存储过程,它大量使用游标。基于集合的解决方案是可能的,因此我得到了三个版本:原始版本、带有表变量的基于集合的版本和完全基于 CTE 的基于集合的版本。我正在为基于 CTE 的解决方案获得良好的指标,但由于 CTE 版本创建的查询的大小和复杂性,我对发布它持谨慎态度,直到我对它进行了尽可能多的尽职调查。
现在我意识到 SQL 取出的锁是它认为需要在给定时间点取出的锁,并且在加载的生产服务器上它的行为可能会有所不同,但我希望它能给我一种感觉它会表现。
目前我正在使用探查器并保持事务打开以便我可以运行sp_lock
,但想知道我是否遗漏了 SQL Server 2008 中的一个技巧。
或者,我试图说服自己分析器在插入表变量时返回大量读取是可以的(对于给定的值 Ok),但我没有说服自己。CTE 解决方案的读取次数是 table-var 版本的一半,而 table-var 版本的高读取计数似乎完全取决于插入。在持续时间方面,CTE 和表 var one 大致相同,执行时间比基于游标的方法快 150-200%。
有没有人能够解释我在 SQL Profiler 中看到的一些行为?采取以下两批:
exec sp_executesql N'
declare @t table (
x int
)
insert into @t (x) select top 10 number from dbo.gennumbers
select * from @t
union
select * from @t
'
exec sp_executesql N'
select top 10 number from dbo.gennumbers
union
select top 10 number from dbo.gennumbers
'
Run Code Online (Sandbox Code Playgroud)
(这是我正在进行的一些重构的简化;实际上,临时表是通过在最终查询中重用的 CTE 填充的,因此通过缓存数据来减轻 SQL Server 需要执行的重复工作量)。
在这个例子中,GenNumbers 只是一个数字表,只有一个列,只包含一个连续运行的数字 - 没什么特别的。
在探查器中,我得到以下结果:
第 1 批,带有临时表:
事件 TextData 读取 SP:StmtCompleted INSERT INTO(...) 27 SP:StmtCompleted SELECT * FROM ... 6 SQL:StmtCompleted exec …