JSON列或传统列

时间:2015-10-30 14:07:09

标签: sql-server json sql-server-2012 database-administration

我的团队正在开发一个发票模块,我们的用户需要能够将订单项添加到发票中并将这些订单项存储在我们的数据库中。这些订单项可以在初始创建后进行编辑。

发票的订单项看起来像这样。

LineItemName
EnteredBy
Quantity
CostPerUnit
Subtotal

我们的一位团队成员建议我们将行数据存储到JSON列而不是多个SQL列中。他的论点是,将所有行项数据存储到单个JSON列中更简单,而不是编写代码来检测哪些行项目可能已被删除,更新,重新排序或以其他方式从数据库中操作。原始状态。

之前我没有使用过JSON专栏,而且我可以告诉他们在使用这些专栏时会遇到许多性能问题,以及在构建JSON数据列的查询时会遇到一些额外的复杂性。我们将不得不报告这些订单项,因此性能绝对是一个问题。我们还运行SQL Server 2012,据我所知,除非我们升级到SQL Server 2016,否则不包含对JSON列的本机支持。附注,我们很可能会在未来2 - 3年内迁移到MYSQL。

有人可以就正确的电话是什么提供一些指导吗?我的直觉是,我们应该利用现有方法并编写额外的代码来检测数据库更改,以避免后期出现性能问题和报告复杂性。

2 个答案:

答案 0 :(得分:10)

我会尝试给出稍微不同的答案:)

如果您期望进行大量更新和计算,请使用关系列。引用和更新列比更新和引用JSON字段更好。在这种情况下,您正在优化DML性能,可能还有一些分析。

如果您的信息很少被更改,并且您想要避免过多的JOIN,或者您的应用程序需要JSON,请使用JSON / XML。在这种情况下,您将优化读取和加载性能。

在上一个答案中,你可以看到关系模式的很多好处,我不能说这是错误的。但是,我会提到JSON可以帮助的几个用例:

  1. 想象一下,您有大型表格,您需要使用1M发票行项目加入100K发票。在关系模型中,您将有两个表扫描和JOIN,而使用JSON / XML,您将具有单个表扫描。如果您的应用程序希望响应格式化为JSON(例如,您通过Ajax调用将行项目作为JSON发送到angular,Knockout或其他JavaScript模板),JSON将是完美的选择。想象一下,与使用JSON的单表扫描相比,如何查询更复杂的结构。 De-normalization是提高查询性能的最古老的技巧之一,而JSON只是物化视图,OLAP多维数据集中的聚合等非规范化技术之一。它不是解决所有问题的解决方案,但它在某些情况下有所帮助
  2. 想象一下,您需要导入父/子表。您需要导入一个发票行,获取@@ identity,使用该标识插入相关的订单项,然后对每个导入的发票重复此操作。另一种方法是通过设置IDENTITY INSERT ON强制id。使用JSON / XML,如果您将每个发票中的行项目格式化为JSON,则可以使用简单的批量导入,这是加载数据的最快方式。
  3. 这些是人们切换到NoSQL(例如MongoDB或Azure DocumentDB)的一些原因。在SQL 2016中将支持JSON,在以前的版本中,您需要使用XML,但原则是相同的。

    在您的情况下,您似乎经常更新订单项,并且您不需要快速读取/加载方案,因此我建议使用关系架构。

答案 1 :(得分:5)

简答:不要存储在JSON中,使用列,这就是他们在那里的原因。

答案很长

您正在使用关系数据库来存储数据,使用这些软件提供的功能来存储和组织数据。

由于它已经出现在注释中,将值存储在各自的列中,允许您执行不同的聚合,对这些列进行过滤而无需解析非关系数据结构的开销(最可能使用第三方插件/ CLR /功能/其它)。

此外,JSON数据没有固定的结构。如果不解析字段并编写自定义验证,则无法验证存储在JSON字段中的数据的一致性。

在一个字段中存储多个数据也意味着,您不能(或不容易)

  • 在嵌入字段上使用约束
  • 您无法强制执行嵌入字段的每个字段的结构,有效范围和有效值
  • 定义嵌入字段的数据类型
  • 索引数据(既不包括它们)
  • 在这些字段中汇总/搜索
  • 扩展系统
  • 查询嵌入式元数据的元数据,字段列表等

数据库服务器不能

  • 跟踪每个字段的索引统计信息
  • 使用JSON字段优化查询(因为提取数据所需的字符串操作)
  • 无法以最佳方式存储每个字段的数据。

以上内容很重要,但没有一个列表完整。

你会赢得什么?

  • 一些字段名称。
  • 数据库具有一定的灵活性,但应用程序中的功能要复杂得多,因为所有的验证都应该在应用程序中完成两次 - 当你想写时和读数据时。
  • 当您必须在JSON字段中修复某些内容时,这是一件非常令人头疼的事。

作为替代方案,您可以使用XML列,SQL Server支持它,并且上面的一些内容不是问题,但是:它仍然没有固定的结构。 (如果有,您可以将数据存储在传统列中。在这两种情况下,您都必须手动指定结构。)

注意:您选择用于存储数据的格式当然是基于意见的,但根据经验,只要满足您的需求并使用序列化数据,就可以使用传统列。特别是如果你想只使用它的某些部分进行任何计算。

何时可以存储序列化数据 如果强制执行一致性并不重要,您将永远不会将其用于统计查询或过滤。 (但是,在大多数情况下,永远不是真的:))