Более быстрый способ просмотра данных LINQ - PullRequest
2 голосов
/ 22 октября 2010

Я пишу код, который извлекает данные из таблиц базы данных и записывает их в XML-файл (который будет выбран другим процессом). Есть около 60000 записей, и каждая запись может иметь несколько субъектов, то есть член может иметь несколько контактов, каждый контакт может иметь несколько телефонных номеров и т. Д. Весь процесс занимает несколько часов, и я сократил медлительность до фактического извлечение данных (не запись 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, которые замедляли его, поэтому я попытался записать элементы непосредственно в файл XML, используя циклы For:

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?

Ответы [ 3 ]

4 голосов
/ 22 октября 2010

Каждый проход внутреннего цикла попадает в базу данных.Используйте выражение 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...

В качестве идентификатора вы можете использовать синтаксис XML в VB.Net ...

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>
2 голосов
/ 22 октября 2010

Я думаю, что ваша проблема в отложенной загрузке Linq.

Первое, что я сделаю, - это запустите SQL Profiler и выясните, так ли это, и тысячи соединенийоткрывать и закрывать доступ к каждому уровню данных.

Если это так, я откажусь от Linq и использую SqlDataReader, что, вероятно, займет несколько секунд, чтобы выполнить эту работу.

Если это произойдетодин большой запрос в профилировщике и на стороне SQL медленный, я посмотрю на индексы и оптимизирую индексы базы данных.

1 голос
/ 22 октября 2010

Это должно быть значительно быстрее по указанным выше причинам.

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()**

Он выберет все в одном вызове доступа к базе данных вместо N + 1

, также вы можете попробовать параллельное соединение ..как-то так ... У меня нет редактора.

dim output = from m in dc.members.asparallel().select(function (m)  new XElement("member", New XElement("id", m.member_id), etc..)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...