获取具有多对多关系的复杂数据的最快方法?
Fastest way to fetch complex data with many-to-many relationships?
运行SQL Server 2014
。我有多个 table 与其他 table 具有多对多关系。很多时候,我需要从 table A
中获取 N 行,同时显示项目 table B
和 C
。我想尽可能高效地做到这一点。
最有效的方法是什么?下面的一些想法。
注意:客户端和服务器不一定在同一个网络。
天真的做法
天真的方法看起来像这样:
- 客户端向服务器请求来自 table
A
的 N 行并反序列化它们。
- 对于
A
中的每个项目,客户端随后向服务器询问其在 B
中的关联项目。
- 对于
A
中的每个项目,客户端随后向服务器询问其在 C
中的关联项目。
这会导致大量的数据库往返,在慢速网络(即 WAN
)上会导致严重的性能问题。这根本不是一个选择。
XML 方法
通过让SQL Server
生成XML
,我们可以将结构化数据传递给客户端。
- 客户端向服务器请求
XML
来自 table A
的 N 行,其中每行包含来自 B
和 C
的项目。然后 XML 被反序列化为 C#
. 中的一个随时可用的对象
它可能看起来像这样:
<data>
<a_collection>
<a>
<id>1</id>
<title>A Title<title>
<b_collection>
<b>
<id>123</id>
<description>B stuff here</description>
</b>
<b>
<id>124</id>
<description>Other B stuff here</description>
</b>
</b_collection>
<c_collection />
</a>
</a_collection>
</data>
我喜欢这种方法,但速度很慢。随着行数的增加,关系变得更加复杂,XML
在 SQL Server
上的序列化变得缓慢 。有没有办法以某种方式在 CPU 和 RAM 使用方面改进 XML
序列化?
JSON 方法
当 SQL Server 2016
发布时,我们将可以选择使用 JSON
而不是 XML
。也许上面的 XML
方法可以转换为 JSON
并且可能受益于更快的序列化程序?但是,当您无法再从 System.Xml.Serialization
中受益时,您将如何反序列化对象?
WCF 方法
在客户端和数据库服务器之间创建一个额外的层似乎是个好主意。这样的解决方案与 XML
方法相比如何?
其他方法?
应该有其他有效的方法将结构化数据从 SQL Server
传送到客户端。
在你的情况下,XML 方法是我的...
编辑:我认为最好考虑四个不同的问题:
- 正在获取数据(连接、过滤、聚合)
- 正在准备您的数据(XML、JSON、其他)
- 正在传输您的数据(字节大小)
- 在您的应用程序中反序列化
ad 1) 性能影响:~85%
让 SQL 服务器完成艰巨的工作...假设设计良好的结构和合适的索引,将没有更快的方法来获取您的数据。 SQL 服务器具有强大的能力,可以找到 "most bestest" 加入的方式,以完全按照您需要的方式过滤和聚合数据。不会有更好的办法。如果您的数据有大量未更改的可预加载 tables,您可以使用 "load-on-start".
来加快速度
我会使用参数化 table 值 内联 (!!!) UDF。它们在维护和性能方面是最好的,您可以轻松地将您的需求分成模块化的部分。
ad 2) 性能影响:~4%
我会对 1) 中的 UDF 做额外的 SELECT ... FOR XML PATH()
。使用 FOR XML PATH
,您可以完全控制给定 XML 的输出。稍后您可以轻松地将其更改为 JSON 方法。您可能会想到自己的格式(csv 之类的?),但我不会...
ad 3) 性能影响:~1%
传输的数据将尽可能接近最小值。自己的格式将是最小的,但是 JSON 足够小而 XML 也没有那么大......我认为,你真的不必太在意字节大小。 .. XML 是最强大的(通过属性添加元数据)。
ad 4) 性能影响:~10%
在 C# 中,您可以很好地支持将数据转换为可查询结构。一种非常简单的方法是 DataSet.ReadXml
另一种简单的方法是XmlDocument.LoadXml
使用 pe 定义的结构,您可以将 XML 直接反序列化为用户定义的 class...
设施
AFAIC 是第 1 点唯一相关的点)。传输的数据在任何情况下都是完全相同的,或多或少有一些字节开销......即使没有显式序列化,也会有一些隐式序列化和反序列化,以便将您的数据发送到应用程序。性能差异并不重要...
最后但同样重要的是,这种方法很容易集成到面向服务的体系结构中...
运行SQL Server 2014
。我有多个 table 与其他 table 具有多对多关系。很多时候,我需要从 table A
中获取 N 行,同时显示项目 table B
和 C
。我想尽可能高效地做到这一点。
最有效的方法是什么?下面的一些想法。
注意:客户端和服务器不一定在同一个网络。
天真的做法
天真的方法看起来像这样:
- 客户端向服务器请求来自 table
A
的 N 行并反序列化它们。 - 对于
A
中的每个项目,客户端随后向服务器询问其在B
中的关联项目。 - 对于
A
中的每个项目,客户端随后向服务器询问其在C
中的关联项目。
这会导致大量的数据库往返,在慢速网络(即 WAN
)上会导致严重的性能问题。这根本不是一个选择。
XML 方法
通过让SQL Server
生成XML
,我们可以将结构化数据传递给客户端。
- 客户端向服务器请求
XML
来自 tableA
的 N 行,其中每行包含来自B
和C
的项目。然后 XML 被反序列化为C#
. 中的一个随时可用的对象
它可能看起来像这样:
<data>
<a_collection>
<a>
<id>1</id>
<title>A Title<title>
<b_collection>
<b>
<id>123</id>
<description>B stuff here</description>
</b>
<b>
<id>124</id>
<description>Other B stuff here</description>
</b>
</b_collection>
<c_collection />
</a>
</a_collection>
</data>
我喜欢这种方法,但速度很慢。随着行数的增加,关系变得更加复杂,XML
在 SQL Server
上的序列化变得缓慢 。有没有办法以某种方式在 CPU 和 RAM 使用方面改进 XML
序列化?
JSON 方法
当 SQL Server 2016
发布时,我们将可以选择使用 JSON
而不是 XML
。也许上面的 XML
方法可以转换为 JSON
并且可能受益于更快的序列化程序?但是,当您无法再从 System.Xml.Serialization
中受益时,您将如何反序列化对象?
WCF 方法
在客户端和数据库服务器之间创建一个额外的层似乎是个好主意。这样的解决方案与 XML
方法相比如何?
其他方法?
应该有其他有效的方法将结构化数据从 SQL Server
传送到客户端。
在你的情况下,XML 方法是我的...
编辑:我认为最好考虑四个不同的问题:
- 正在获取数据(连接、过滤、聚合)
- 正在准备您的数据(XML、JSON、其他)
- 正在传输您的数据(字节大小)
- 在您的应用程序中反序列化
ad 1) 性能影响:~85%
让 SQL 服务器完成艰巨的工作...假设设计良好的结构和合适的索引,将没有更快的方法来获取您的数据。 SQL 服务器具有强大的能力,可以找到 "most bestest" 加入的方式,以完全按照您需要的方式过滤和聚合数据。不会有更好的办法。如果您的数据有大量未更改的可预加载 tables,您可以使用 "load-on-start".
来加快速度我会使用参数化 table 值 内联 (!!!) UDF。它们在维护和性能方面是最好的,您可以轻松地将您的需求分成模块化的部分。
ad 2) 性能影响:~4%
我会对 1) 中的 UDF 做额外的 SELECT ... FOR XML PATH()
。使用 FOR XML PATH
,您可以完全控制给定 XML 的输出。稍后您可以轻松地将其更改为 JSON 方法。您可能会想到自己的格式(csv 之类的?),但我不会...
ad 3) 性能影响:~1%
传输的数据将尽可能接近最小值。自己的格式将是最小的,但是 JSON 足够小而 XML 也没有那么大......我认为,你真的不必太在意字节大小。 .. XML 是最强大的(通过属性添加元数据)。
ad 4) 性能影响:~10%
在 C# 中,您可以很好地支持将数据转换为可查询结构。一种非常简单的方法是 DataSet.ReadXml
另一种简单的方法是XmlDocument.LoadXml
使用 pe 定义的结构,您可以将 XML 直接反序列化为用户定义的 class...
设施
AFAIC 是第 1 点唯一相关的点)。传输的数据在任何情况下都是完全相同的,或多或少有一些字节开销......即使没有显式序列化,也会有一些隐式序列化和反序列化,以便将您的数据发送到应用程序。性能差异并不重要...
最后但同样重要的是,这种方法很容易集成到面向服务的体系结构中...