我发现使用 TVP 将多个值传递给存储过程更加容易和快捷,尤其是在处理几列和几百行时,因为它消除了额外数据解析的需要。为什么有人会选择 XML 或 JSON 而不是 TVP?在哪些用例中它们提供更好的性能或优势?如果有机会,你会在这三者之间选择哪一个?谢谢!
我发现使用 TVP 将多个值传递给存储过程更加容易和快捷,尤其是在处理几列和几百行时,因为它消除了额外数据解析的需要。为什么有人会选择 XML 或 JSON 而不是 TVP?在哪些用例中它们提供更好的性能或优势?如果有机会,你会在这三者之间选择哪一个?谢谢!
仅当由于某些框架限制而无法使用表值参数(TVP)时。
从性能角度来看,传递 JSON 或 XML 的问题在于,大多数人会编写(或复制/粘贴)一些糟糕的字符串拆分函数,并将其与查询中的拆分字符串关联起来。使用 SQL Server 的原生STRING_SPLIT函数时,问题仍然存在。
SQL Server 的优化器无法分析这些字符串的内容,即使内容被拆分,除非您先将它们放入 #temp 表中。请记住,即使已建立索引,也不会为 @table 变量生成统计信息。
EF Core 团队曾尝试使用 JSON 代替 IN 子句,但实际结果却是一场性能灾难。他们早就收到了警告,但还是坚持这么做。我建议对这种失职行为判处监禁。
但回过头来看,TVP 由 @table 变量支持,而 @table 变量在 SQL Server 中存在问题。即使采用各种方案来获取表级基数(表中有多少行),缺乏有关列中数据的统计信息通常会导致性能问题。
您通常会发现自己将 TVP 的内容转储到 #temp 表中,因为它们往往会带来更好的计划选择。
我想不出 JSON 和 XML 之间有什么特别相关的区别。因此,这实际上是 TVP 与结构化字符串数据(在答案的其余部分,我将仅使用 JSON 来表示它们中的任何一个,或任何其他结构化字符串数据协议)。
TVP 的真正问题在于其缺乏灵活性和不通用性。
它们要求将用户定义的表类型与过程的标题分开声明 - 这使得过程调用者查找形状成为障碍,并且使过程制定者改变形状成为障碍(这需要撤回过程,改变表类型,然后恢复过程)。
它们是仅限输入的,因此使用 JSON 的技术必须保留用于输出参数(反过来,这些有时是必需的,因为您不能嵌套插入执行)。
当从客户端语言(即 TSQL 之外)调用过程时,它们往往更难使用。
通常,这些看似尴尬的功能(如 TVP)涵盖了一些不寻常的情况,因此,我发现 TVP 在数据量非常大的情况下比 JSON 表现更好并不奇怪。我可能首先倾向于使用临时表,但随后你可能会失去可重入性。
但是对于“几列和几百行”,现在我会首先尝试 JSON,因为相同的技术可以一致地应用于更多种类的情况。