Pro SQL Server 关系数据库设计和实施:可扩展性和性能的最佳实践是优秀数据库设计理念的可靠来源。作为实体-属性-值的替代方案,它建议使用动态 SQL 来允许用户向表中添加新的稀疏列。
对我来说,这个想法很糟糕。添加新列需要架构修改锁。这是一个非常严重的锁,我宁愿我的用户无法获得它。
稀疏列是否有任何属性使得允许用户采取如此严重的锁定并不像其他类型的列那样可怕?
Pro SQL Server 关系数据库设计和实施:可扩展性和性能的最佳实践是优秀数据库设计理念的可靠来源。作为实体-属性-值的替代方案,它建议使用动态 SQL 来允许用户向表中添加新的稀疏列。
对我来说,这个想法很糟糕。添加新列需要架构修改锁。这是一个非常严重的锁,我宁愿我的用户无法获得它。
稀疏列是否有任何属性使得允许用户采取如此严重的锁定并不像其他类型的列那样可怕?
虽然值得称赞,但您对添加和删除列的担心大多是没有根据的。
添加可空列是仅元数据操作:也就是说,它只需要对内部表中的数据库表定义进行微小更改,并且不需要重写聚集索引和所有非聚集索引。这意味着这种修改非常快。同样,删除列也是仅元数据操作,因为存储引擎将简单地忽略该数据,直到最终覆盖每个页面时没有该数据。
您可以在这个小提琴中看到它的实际作用。
SET STATISTICS IO ON
用于显示表本身的读取,并且您可以看到它仅在添加非可空列时发生。你真正关心的应该是:
例如,一个长时间运行的
SELECT
持有Sch-S
表上的锁。ALTER
尝试获取Sch-M
锁并等待。SELECT
然后,所有其他和修改查询都堆积在它后面,等待Sch-S
它们无法获取的自己的锁。不幸的是,这无法避免使用
WAIT_AT_LOW_PRIORITY
,因为尚未为这种类型的 实现ALTER
。最好的办法是将以下内容放在 之前ALTER
:为什么不呢?(当然我可以列出一堆理论上的原因,但是……)无论您的用户进行架构更改还是您作为开发人员进行相同的更改,都需要架构修改锁。大多数最终用户拥有此访问权限的用例都处于有限的世界中,他们只会自食其果或自毁团队。在多租户环境中,不应存在交叉,租户无论如何都应该分开。
可以实施进一步的应用程序设计措施,以最大限度地减少最终用户给自己造成的伤害,例如延迟执行模式更改(例如,安排一个队列在非工作时间运行生成的 SQL)并限制对此功能的访问,仅限应用程序的管理特权用户。
再次强调,我不这么认为,解决方案应该是架构解决方案。除了我上面提到的,其他可以减轻这种风险的设计选择是要么有一定数量的不同数据类型的列,当最终用户需要自定义列时,这些列会单独映射,或者有一个单独的表,例如,
ObjectNameExtended
用户动态添加新列,这样架构修改锁只会影响自定义,至少不会影响本机应用程序。此外,正如 Erik Darling 指出的那样,稀疏列有一系列可能非常蹩脚的限制,例如阻止您压缩它们所属的任何表/索引:
另外,来自该网络的维护公告: