我的问题在于对这一问题进行了一些跟进:Efficient Way To Query Nested Data。但是,我想稍微概括一下,并且可能会更新它,因为它已经有6年了,并且可能有新的更好的选择(?)。
我在MS SQL Server数据库中有一个典型的主/细节关系(虽然我认为数据库不可知的答案可以帮助任何人,因为这是一个非常普遍的问题)。
我正在寻找效果最好的方法从数据库中读取并在内存中加载这样的嵌套结构(到数据对象中)。我意识到答案可能是“它取决于”,在这种情况下它取决于什么?
这些是我提出的替代方案:
SELECT * 来自MasterTable 在MasterTable.Id = DetailTable.MasterId
上加入DetailTable[如果我没有弄错的话,那就是在执行等效数据模型对象的热切加载时ORM将创建的内容......例如,在实体框架中使用.Include]
这种方法的缺点是数据重复,这是因为必须“展平”这种分层结构,为每个DetailTable记录重复所有需要的MasterTable字段。根据结果集的总大小和MasterTable中所需的字段,这可能会产生糟糕的性能(在数据库本身,以及之后,将所有数据传输到您的进程......加上我不是确保最终的数据对象实现更快。)
SELECT MasterTable。*, (SELECT * FROM DetailTable WHERE MasterTable.Id = DetailTable.MasterId FOR XML PATH('Detail'),TYPE) 来自MasterTable FOR XML PATH('Master')
我不完全确定SQL Server的功能是什么,但输出是分层的,因此,没有数据重复(尽管有一些XML格式化过程成本,我猜,并且XML标记作为附加数据)。然后增加了将XML结果反序列化为数据对象的步骤,但这也不是非常昂贵(既不是CPU也不是代码行,因为它通常已经内置在大多数编程框架中)。
根据我的经验,这种方法比第一种方法提供了更好的结果,并且差异随着连接表的数量,结果集的大小等的增加而增加。
SELECT * FROM MasterTable,和 SELECT * FROM DetailTable
然后在内存中执行数据对象层次结构实现。这可以有效地完成,就像原始链接中的答案一样,每个结果集都有一个传递:
查询MasterId订购的所有主人,然后查询MasterId订购的所有详细信息。然后,使用两个嵌套循环,迭代主数据并为主循环中的每一行创建一个新的Master对象,并在它们具有与当前Master对象相同的MasterId时迭代细节,并在嵌套循环中填充其_details集合。
这需要2个查询(或者每个附加的详细信息表需要N个),但结果集的总大小和传输到调用进程的内容尽可能小。
直到最近(我还没有意识到SQL Server的FOR XML功能),在10个场景中的9个中我发现选项3总是明显优于1(我很少使用,实际上)。 ..但现在我对实际场景中的选项2感到好奇,其中涉及大量数据,因此将在我有需要的下一个项目中做一些快速比较。
您对FOR XML有什么看法/经验,您对这些替代方案有什么看法?是否还有其他建议?
提前致谢。