2010-08-11 4 views
1

У меня есть несколько XML-файлов, и каждый файл содержит данные «корневых объектов», которые я анализирую с использованием Linq для XML, а затем создаю фактические корневые объекты, которые я сохраняю, используя NHibernate и репозиторий резкой архитектуры. Я начал оптимизировать ввод данных и управлять добавлением 30000 объектов примерно через 1 час 40 минут в базу данных. Однако это все еще слишком медленно.Производительность вставки/поиска NHibernate

Я думаю, что одна бутылка шеи - это поиск объектов в базе данных, требующих ввода-вывода. Объекты нужно искать для повторного использования.

Корневой объект имеет несколько авторов:

public virtual IList<Author> Authors { get; set; } 

Авторы имеют такую ​​структуру:

public class Author : Entity 
    { 
public virtual Initials Initials { get; set; } 
     public virtual ForeName ForeName { get; set; } 
     public virtual LastName LastName { get; set; } 
    } 

я достиг большой скорости вверх с помощью типизированных Id (то, что я обычно не делать):

public class LastName : EntityWithTypedId<string>, IHasAssignedId<string> 
    { 
     public LastName() 
     { 
     } 
     public LastName(string Id) 
     { 
      SetAssignedIdTo(Id); 
     } 
     public virtual void SetAssignedIdTo(string assignedId) 
     { 
      Id = assignedId; 
     } 
    } 

Что я смотрю (и, возможно, создать), как это:

LastName LastName = LastNameRepository.Get(TLastName); 

         if (LastName == null) 
         { 
          LastName = LastNameRepository.Save(new LastName(TLastName)); 
          LastNameRepository.DbContext.CommitChanges(); 
         } 
         Author.LastName = LastName; 

Ищу авторов вверх, как это:

propertyValues = new Dictionary<string, object>();    
propertyValues.Add("Initials", Author.Initials); 
        propertyValues.Add("ForeName", Author.ForeName); 
        propertyValues.Add("LastName", Author.LastName); 
        Author TAuthor = AuthorRepository.FindOne(propertyValues); 

        if (TAuthor == null) 
        { 
         AuthorRepository.SaveOrUpdate(Author); 
         AuthorRepository.DbContext.CommitChanges(); 
         Root.Authors.Add(Author); 
        } 
        else 
        { 
         Root.Authors.Add(TAuthor); 
        } 

Могу ли я улучшить это? Следует ли использовать хранимые процедуры/HQL/pure SQL/ICriteria для выполнения поиска? Могу ли я использовать некоторую форму кеширования, чтобы ускорить поиск и уменьшить IO? Кажется, что CommitChanges необходимо, или я должен все превратить в транзакцию?

Я уже очищаю свою сессию и т. Д. Каждые 10 корневых объектов.

Любая обратная связь будет очень радушна. Спасибо заранее.

С наилучшими пожеланиями,

Christian

ответ

1

Честно говоря, я бы сказал, что вы не должны быть даже с помощью SA/NHibernate что-то вроде этого. Это массовый импорт данных из XML. Лучшим выбором будет инструмент ETL, такой как SSIS. Даже обработанный вручную процесс на сервере БД будет работать лучше - шаг 1, загрузите XML в таблицу, шаг 2, выполните операцию UPSERT. Кстати, SQL 2008 представила команду MERGE для операций UPSERT, которая может быть полезной.

Я также согласен с комментарием Дэна - действительно ли нужно обрабатывать инициалы, имя и фамилию как отдельные объекты? Рассмотрение их как простых строк могло бы повысить производительность. Что в вашей модели домена указывает, что они являются сущностями в своем собственном праве?

Если вы действительно должны продолжать использовать SA/NHibernate, есть чтение этого: http://www.lostechies.com/blogs/jimmy_bogard/archive/2010/06/24/bulk-processing-with-nhibernate.aspx

Предложение в блоге Джимми о дозаторов должно помочь SELECT, довольно много.Если вы планируете обрабатывать пакет из 250 записей за один раз, сделайте все SELECT как одну команду NH, обработайте все данные, а затем сделайте все обновления в виде еще одной отдельной партии (которая, я считаю, использует использование EntityWithTypedId и adonet.batch_size настройка конфигурации поможет достичь)

И наконец - относительно утверждения, которое я анализирую с использованием Linq для XML, - это действительно лучший способ сделать это? Я предполагаю, что это может быть, учитывая размер вашего входного файла, но знаете ли вы, что просто десериализовать XML-файл в граф объектов? SO не позволит мне опубликовать ссылку на страницу, описывающую это, потому что я еще не получил достаточной репутации, но если вы хотите ее прочитать, Google «не анализирует этот xml», и первая статья объяснит Это.

Надеюсь, это поможет. Jon

+0

В итоге я использовал xsd2code. убедитесь, что если ваш xml содержит данные dtd, используйте: BlaClassBlaClass = ((BlaClass) (serializer.Deserialize (System.Xml.XmlReader.Create (новый XmlTextReader (путь к файлу), новый System.Xml.XmlReaderSettings() {ProhibitDtd = false })))); – cs0815

0

Первое, что я хотел бы сделать это упростить организацию Авторы, как я не думаю, что вам нужно Инициалы, имя, и объекты LastName как отдельные объекты. Я думаю, что с помощью простых строк будет более эффективным:

public class Author : Entity 
{ 
    public virtual string Initials { get; set; } 
    public virtual string ForeName { get; set; } 
    public virtual string LastName { get; set; } 
} 
+0

спасибо - это остаток от того, когда я попытался использовать lookuptables для имен - где у меня была строка int, а не фактическая строка в качестве первичного ключа. Затем я понял, что поиск int занимает много времени - поэтому я заплатил за эффективность вставки с памятью. – cs0815