我正在编写从数据库表中提取数据并将其写入XML文件的代码(由另一个进程获取)。有大约60,000条记录,每条记录可以有多个参与者,即一个成员可以有多个联系人,每个联系人可以有几个电话号码等。整个过程需要几个小时,我已经将实际的缓慢范围缩小到了拉取数据(不写XML,或拉动后的任何数据处理等)。我用两种不同的方式尝试了代码,结果相似。首先,我利用LINQ查询并在一个语句中创建所有元素:
Dim output =
From m In dc.members
Select New XElement("member", _
New XElement("id", m.member_id), _
New XElement("address", m.Address), _
New XElement("city", m.City), _
New XElement("state", m.State), _
New XElement("contacts", _
From c in m.contacts
Select New XElement("contact", _
New XElement("contact_name", c.name), _
New XElemdnt("contact_address", c.address), _
...
我认为可能是所有XElements的创建减慢了速度,所以我尝试使用For循环将元素直接写入XML文件:
Dim output As New Xml.XmlTextWriter("my.xml", Nothing)
For Each m in dc.members
output.WriteStartElement("member")
output.WriteElementString("id", m.member_id)
output.WriteElementString("address", m.Address)
output.WriteElementString("city", m.City)
output.WriteElementString("state", m.State)
output.WriteStartElement("contacts")
For Each c in m.contacts
output.WriteStartElement("contact")
output.WriteElementString("contract_name", m.name)
output.WriteElementString("contract_address", m.address)
....
这使得该过程花费的时间几乎没有变化。然后我尝试剥离所有元素并将代码缩减到数据库拉动,同样慢。
是否有更快/更好的方法从数据库中提取所有这些规范化数据,以便我可以尽快将其转换为XML文件?
答案 0 :(得分:4)
内循环的每次传递都是命中数据库。使用LINQ表达式仅在一次点击中获取所需的数据。在C#中(抱歉,我不知道VB.Net)它看起来像是:
var members = from m in dc.members
select new {
m.member_id,
m.Address,
...
contacts = from c in m.contacts
select new {
c.name,
c.address
}
};
var output = from m in members
select new XElement...
作为旁注,您可以在VB.Net中使用XML语法......
Dim output = _
From m In members _
Select <member>
<id><%= m.member_id %></id>
<address><%= m.Address %></address>
...
<contacts>
<%= From c in m.contacts _
Select <contact>
<contact_name><%= c.name %></contact_name>
<contact_address><%= c.address %></contact_address>
...
</contact>
%>
</contacts>
</member>
答案 1 :(得分:2)
我认为您的问题是Linq的延迟加载。
我要做的第一件事就是运行SQL事件探查器并查明是否是这种情况,并且打开和关闭了数千个连接,以访问每个级别的数据。
如果是这种情况,我会废弃Linq并使用SqlDataReader
,这可能需要几秒钟来完成这项工作。
如果在探查器和SQL端的一个大查询很慢,我将查看索引并优化数据库索引。
答案 2 :(得分:1)
由于上述原因,这应该明显加快
Dim output =
From m In dc.members.**Include("contacts")**
Select New XElement("member", _
New XElement("id", m.member_id), _
New XElement("address", m.Address), _
New XElement("city", m.City), _
New XElement("state", m.State), _
New XElement("contacts", _
From c in m.contacts
Select New XElement("contact", _
New XElement("contact_name", c.name), _
New XElemdnt("contact_address", c.address)
.....)**.tolist()**
它将在一个db访问调用中选择所有内容而不是N + 1
你也可以尝试并行linq ..这样的东西......我没有可用的编辑器。
dim output = from m in dc.members.asparallel().select(function (m) new XElement("member", New XElement("id", m.member_id), etc..)