JSON列或传统列

Hun*_*son 5 sql-server json database-administration sql-server-2012

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

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

LineItemName
EnteredBy
Quantity
CostPerUnit
Subtotal
Run Code Online (Sandbox Code Playgroud)

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

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

任何人都可以提供一些关于正确呼叫的指导吗?我的直觉是我们应该利用现有方法并编写额外的代码来检测数据库的变化,以避免后来出现性能问题和报告复杂性.

Jov*_*SFT 10

我会尽量给出一个略有不同的答案:)

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

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

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

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

这些是人们切换到NoSQL的一些原因(例如MongoDB或Azure DocumentDB).在SQL 2016中将支持JSON,在以前的版本中,您需要使用XML,但原则是相同的.

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


Pre*_*red 9

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

答案很长

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

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

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

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

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

数据库服务器不能

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

上述内容很重要,但没有一个列表是完整的.

你会赢得什么?

  • 一些字段名称.
  • 数据库具有一定的灵活性,但应用程序中的功能要复杂得多,因为所有的验证都应该在应用程序中完成两次 - 当你想要写入和读取数据时.
  • 当您必须在JSON字段中修复某些内容时,这是一个巨大的麻烦.

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

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

你什么时候可以存储序列数据: 当它并不重要,执行的一致性,你绝不会用它来统计查询或过滤.(但是,在大多数情况下,永远不会是真的:))