Sql server 在不牺牲性能的情况下存储大型文本字段的可维护方式是什么?
我一直在围绕这个问题跳舞有一段时间了,但它不断地出现。我们有一个系统,我们的表可能从最初存储为Sql server 在不牺牲性能的情况下存储大型文本字段的可维护方式是什么?,sql-server,database,Sql Server,Database,我一直在围绕这个问题跳舞有一段时间了,但它不断地出现。我们有一个系统,我们的表可能从最初存储为NVARCHAR(150)的描述开始,然后我们得到一张票,要求将字段大小扩展到250,然后是1000等等 在我们添加到大多数表中的“备注”字段和/或“说明”字段上重复此循环。当然,我关心的是性能和打破页面的8k限制。然而,我的另一个担忧是,通过将系统中每个表中的这些字段分解为延迟加载的引用,降低了系统的可维护性 所以在这里,我面临着同样的两个选项,它们一直盯着我看。(欢迎其他人)请把你的意见告诉我 将所
NVARCHAR(150)
的描述开始,然后我们得到一张票,要求将字段大小扩展到250,然后是1000等等
在我们添加到大多数表中的“备注”字段和/或“说明”字段上重复此循环。当然,我关心的是性能和打破页面的8k限制。然而,我的另一个担忧是,通过将系统中每个表中的这些字段分解为延迟加载的引用,降低了系统的可维护性
所以在这里,我面临着同样的两个选项,它们一直盯着我看。(欢迎其他人)请把你的意见告诉我
NVARCHAR(MAX)
,并确保我们在所有列表中排除这些字段。基本上永远不要做:SELECT*FROM[TableName]
,除非它只检索一条记录[notes]
表的外键引用
创建表[dbo].[Notes](
[NoteId][int]不为空,
[NoteText][NVARCHAR]
(MAX
)非空)
更新: 我在一个包含100000条记录的样本数据库上运行了几个测试。我发现,由于集群索引扫描,选项1所需的IO“大约”是选项2的两倍。如果我选择了大量记录(1000条或更多),则选项1的速度是选项1的两倍,即使在“选择”中没有包含大文本字段。我要求的行数越少,线条越模糊。我是一个网页大小通常为50左右的web应用程序,因此选项1可以工作,但为了可扩展性,我将在不久的将来将所有实例转换为选项2。我选择选项2
您可以创建一个视图,将两个表连接起来,使每个人都能更轻松地进行转换,然后执行一个清理过程,删除该视图并尽可能使用单个表。TEXT/NTEXT数据类型的长度实际上是无限的,而在记录中几乎不占用任何内容
它附带了一些字符串,比如字符串函数的特殊行为,但是对于次要的“notes/description”类型的字段,这些可能不是什么问题。您想要使用文本字段。文本字段不直接存储在行中;相反,它存储指向文本数据的指针。不过,这对查询是透明的-如果您请求文本字段,它将返回实际文本,而不是指针
本质上,使用文本字段在某种程度上介于两种解决方案之间。它使您的表行比使用varchar小得多,但如果可能的话,您仍然希望避免在查询中询问这些行。选项2更好,原因如下:
只是为了扩展选项2 你可以: 将现有MyTable重命名为MyTable_V2 将“注释”列移动到已联接的注释表中(具有1:1联接ID) 创建一个名为MyTable的视图,该视图连接MyTable_V2和Notes表 在MyTable视图上创建一个INSTEAD OF触发器,将Notes列保存到Notes表中(如果为NULL,则删除任何现有Notes行;如果为非NULL,则插入(如果未找到),否则更新)。对MyTable_V2表执行适当的操作 注意:在MyTable_V2中有一个计算列的情况下,我们在执行此操作时遇到了问题(我认为这就是问题所在,无论哪种方式,我们在使用“异常”表执行此操作时都遇到了障碍) 应编写所有新的插入/更新/删除代码,以便直接在MyTable_V2和Notes表上操作 (可选)在MyTable日志上插入触发器以显示调用它的事实(它可以至少做到这一点,仅当现有行的日期大于24小时时,才使用GetDate()更新预先存在的日志表行,因此每天只更新一次) 当您不再获取任何日志记录时,可以在MyTable视图上删除INSTEAD OF触发器,现在您完全符合MyTable_V2 正如您所猜测的,要实现的麻烦太多了 或者,拖网代码以查找对MyTable的所有引用,并将它们更改为MyT