在SQL中持久化具有可变模式的复杂类型的最有效方法

在SQL中持久化具有可变模式的复杂类型的最有效方法,sql,performance,database-design,self-join,document-database,Sql,Performance,Database Design,Self Join,Document Database,我在做什么 我正在创建一个SQL表,它将为复杂类型的对象提供后端存储机制。我正在努力确定如何以最佳性能完成此任务。我需要能够查询复杂类型的每个简单类型值(例如地址复杂类型中城市的字符串值) 我最初认为可以将复杂类型值作为XML存储在一个记录中,但现在我担心这种设计的搜索性能我需要能够动态创建可变模式,而无需更改数据库访问层的任何内容 我现在的处境 现在我正在考虑创建以下表格 TABLE: Schemas COLUMN NAME DATA TYPE SchemaId

我在做什么

我正在创建一个SQL表,它将为复杂类型的对象提供后端存储机制。我正在努力确定如何以最佳性能完成此任务。我需要能够查询复杂类型的每个简单类型值(例如地址复杂类型中城市的字符串值)

我最初认为可以将复杂类型值作为XML存储在一个记录中,但现在我担心这种设计的搜索性能我需要能够动态创建可变模式,而无需更改数据库访问层的任何内容


我现在的处境

现在我正在考虑创建以下表格

 TABLE:  Schemas
   COLUMN NAME       DATA TYPE
   SchemaId          uniqueidentifier
   Xsd               xml                 //contains the schema for the document of the given complex type
   DeserializeType   varchar(200)        //The Full Type name of the C# class to which the document deserializes.

 TABLE:  Documents
   COLUMN NAME       DATA TYPE      
   DocumentId        uniqueidentifier
   SchemaId          uniqueidentifier

 TABLE:  Values                            //The DocumentId+ValueXPath function as a PK
   COLUMN NAME       DATA TYPE      
   DocumentId        uniqueidentifier
   ValueXPath        varchar(250)
   Value             text
从这些表中,当执行查询时,我将对值表执行一系列自联接。当我想通过DocumentId获取整个对象时,我会使用一个通用脚本来创建一个视图,模拟复杂类型的非规范化数据表


我想知道的

我相信有更好的方法来完成我的目标,但我对不同SQL技术的相对性能优势有点太无知了。具体而言,我不知道以下各项的性能成本:

1 - comparing the value of a text field versus of a varchar field.
2 - different kind of joins versus nested queries
3 - getting a view versus an xml document from the sql db
4 - doing some other things that I don't even know I don't know would be affecting my query but, I am experienced enough to know exist
如果您能提供有关sql中这些性能问题的任何信息或资源,以及如何以更有效的方式解决这个一般问题的建议,我将不胜感激


例如,

下面是我目前计划做的一个例子

我有一个C#类地址,看起来像

public class Address{
     string Line1 {get;set;}
     string Line2 {get;set;}
     string City {get;set;}
     string State {get;set;}
     string Zip {get;set;
}
实例是从
新地址{Line1=“17桑树街”、Line2=“Apt C”、City=“new York”、State=“NY”、Zip=“10001”}

它的XML值看起来像

<Address>
   <Line1>17 Mulberry Street</Line1>
   <Line2>Apt C</Line2>
   <City>New York</City>
   <State>NY</State>
   <Zip>10001</Zip>
</Address>
刚刚加了一笔赏金。。。 我的目标是获得所需的资源,以便为我的应用程序提供一个完全可搜索的数据访问层,并具有从应用程序层生成的数据架构,该数据架构不需要直接数据库配置(即创建新的SQL表),以便向域模型添加新的聚合根


我对使用SQL以外的与.NET兼容的技术的可能性持开放态度,但我会要求对任何此类建议进行充分的证实,以便予以考虑。

不知何故,您想要在SQL中做什么听起来是件痛苦的事情。基本上,您应该将文本字段的内部视为不透明的,就像查询SQL数据库一样。没有为高效查询创建文本字段

如果您只想将序列化对象存储在文本字段中,那么就可以了。但不要试图构建在文本字段内部查找对象的查询

您的想法听起来像是要执行一些连接、XML解析和XPath应用程序来获得一个值。我觉得这不是最有效的方法

因此,我建议:

  • 或者只是将序列化对象存储在数据库中,只需加载它们并在内存中执行所有其他操作
  • 或者,如果您需要查询复杂的数据结构,您可能真的希望查看文档存储/数据库,如或;你也可以查一下。甚至有,尽管我个人不太喜欢
附录,根据您的上述解释

简单地说,这件事不要过分夸张:

  • 如果您只想持久化C#/.NET对象,只需使用XML序列化,一个单独的表并完成它
  • 如果出于某种原因需要存储复杂的XML,请使用专用的XML存储
  • 如果您有一个固定的数据库模式,但它太复杂,无法进行高效查询,请使用内存中的文档存储,在其中保存数据的非规范化版本,以便进行更快的查询(或者简化数据库模式)
  • 如果你真的不需要一个固定的模式,只需要使用一个文档存储,而忘记任何“模式定义”
至于你的解决方案,是的,它可能会以某种方式起作用。如果设置正确,普通SQL模式也可以。但是对于应用XPath,您可能会在每次访问记录时解析整个XML文档,这从一开始就不是很有效


如果要签出文档数据库,则有和的.NET驱动程序。提供了许多Web协议,您可能可以使用VisualStudio的点对点界面轻松创建客户端类。或者只搜索已经搜索过的用户。

部分取决于您的数据库引擎。您正在使用SQL Server,是吗

回答您的话题:

1-比较文本字段和varchar字段的值:如果比较两个db字段,varchar字段更智能。Nvarchar(max)以unicode格式存储数据,数据长度为2*l+2字节,其中“l”是长度。对于性能问题,您需要考虑大表的大小,以便选择索引字段(或不)的最佳方法。p> 2-有时嵌套查询很容易创建和执行,这也是减少查询时间的一种方法。但是,根据复杂性的不同,最好使用不同类型的联接。最好的办法是尝试两种方式。每个查询执行两次或更多次,因为DB引擎在第一次执行时“编译”一个查询,随后的查询速度会更快。测量不同参数的时间并选择最佳选项

“有时您可以重写子查询以使用联接并获得更好的性能。创建联接的优点是,可以按照与查询定义的顺序不同的顺序计算表。使用子查询的优点是,通常不需要扫描子查询中的所有行来计算子查询表达式。例如,EXISTS子查询在看到时可以返回TRUE
DocumentId                              ValueXPath        Value
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Line1    17 Mulberry Street
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Line2    Apt C
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/City     New York
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/State    NY
82415E8A-8D95-4bb3-9E5C-AA4365850C70    /Address/Zip      10001