Сохранение более 1000 записей в базу данных одновременно - PullRequest
11 голосов
/ 11 июня 2009

Я сейчас использую NHibernate. У меня есть ситуация, когда мне нужно сохранить кучу записей в базу данных, например:

var relatedTopics = GetRelatedTopics(topic);
foreach (var relatedTopic in relatedTopics /* could be anywhere from 10 - 1000+ */)
{
    var newRelatedTopic = new RelatedTopic { RelatedTopicUrl = relatedTopic, TopicUrl = topic.Name };
    _repository.Save(newRelatedTopic);
}

Когда нужно сохранить тонну записей, это, очевидно, очень обременительно для обращения к базе данных столько раз. Какой подход лучше? Есть ли какое-то пакетное обновление, которое я могу сделать? Мне лучше использовать DataSet?

Спасибо

Ответы [ 5 ]

14 голосов
/ 11 июня 2009

установка adonet.batch_size может улучшить ситуацию.

Для этого вам нужно

  • установить adonet.batch_size в конфигурации NH

Пример:

    m_sessionFactory = Fluently
         .Configure()
         .Database(MsSqlConfiguration
             .MsSql2005
             .ConnectionString(c => c.FromConnectionStringWithKey("testme"))
             )
         .Mappings(m => m.FluentMappings
             .AddFromAssemblyOf<TestImpl>())
         .ExposeConfiguration(config =>
         {
             config.SetProperty("adonet.batch_size", "1");
             m_configuration = config;
         })
         .BuildSessionFactory();
  • установить размер пакета в сеансе непосредственно перед сохранением

    using (ISession session = m_nhibernateSessionFactory.GetSession())
    using (var tx = session.BeginTransaction())
    {    
       session.SetBatchSize(1000);     
       foreach (var server in serverz)
       {
          session.SaveOrUpdate(server);
       }
       tx.Commit();
    }
    
5 голосов
/ 11 июня 2009

Я считаю, что это то, что вы ищете:

Массовые операции с данными с сессиями NHibernate без состояния

По сути, вместо того, чтобы открывать ISession, вы открываете IStatelessSession, и в своем hibernate.cfg.xml вы можете установить:

 <property name="adonet.batch_size">100</property>
3 голосов
/ 11 июня 2009

Я думаю, у вас есть несколько вариантов в зависимости от вашей ситуации.

Если вы можете использовать NHibernate 2.1 alphas, вы можете попробовать использовать новый исполняемый HQL, который доступен.

http://nhibernate.info/blog/2009/05/05/nh2-1-executable-hql.html

Ответ Тобиаса тоже подойдет. Простая установка размера партии значительно повысит производительность.

Если вы хотите испачкать руки ADO.Net ...

Выполнение групповой вставки в Sql Server возможно с помощью Sql Bulk Copy.

Пример этого здесь: http://dotnetslackers.com/articles/ado_net/SqlBulkCopy_in_ADO_NET_2_0.aspx

Мне кажется, что вы создаете новый объект на основе другого объекта в базе данных. Мне кажется, что это идеальный сценарий использования хранимой процедуры.

1 голос
/ 11 июня 2009

Самый быстрый способ вставить записи - создать текстовый файл и использовать синтаксис LOAD FILE. Большинство баз данных имеют удивительно быстрые реализации для импорта файлов данных в базы данных. Для MySQL см. Ниже:

http://dev.mysql.com/doc/refman/5.1/en/load-data.html

Для других баз данных обратитесь к соответствующему руководству. Это полезно, если вы часто вставляете миллион записей или тысячи записей. В противном случае лучшее, что вы можете сделать, - это создать большой SQL с тысячами вставок и выполнить его непосредственно на соединении с базой данных, пропуская ORM и соответствующие проверки.

1 голос
/ 11 июня 2009

DataSet? Нет. Массовая вставка? Да.

Если вы вставляете столько записей, а вставки довольно просты, вам следует рассмотреть возможность выполнения групповых вставок и извлечения ORM.

...