Сохранение 1000+ записей в базу данных одновременно
В настоящее время я использую 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?
Спасибо
Ответы
Ответ 1
настройка 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();
}
Ответ 2
Я считаю, что это то, что вы ищете:
Операции с массивными данными с сеансами бездействия NHibernate
По существу вместо того, чтобы открывать ISession, вы открываете IStatelessSession, а в hibernate.cfg.xml вы можете установить:
<property name="adonet.batch_size">100</property>
Ответ 3
Я думаю, у вас есть несколько вариантов в зависимости от вашей ситуации.
Если вы можете использовать NHibernate 2.1 alphas, вы можете попробовать использовать новый исполняемый HQL, который доступен.
http://nhibernate.info/blog/2009/05/05/nh2-1-executable-hql.html
Ответ Тобиаса также будет работать. Просто установка размера партии значительно повысит производительность.
Если вы хотите загрязнить свои руки с помощью ADO.Net...
Выполнение массовых вложений на сервере Sql возможно с помощью Sql Bulk Copy.
Пример этого здесь: http://dotnetslackers.com/articles/ado_net/SqlBulkCopy_in_ADO_NET_2_0.aspx
Мне кажется, что вы создаете новый объект, основанный на другом объекте в базе данных. Для меня это кажется идеальным сценарием для использования хранимой процедуры.
Ответ 4
DataSet? Нет.
Массовая вставка? Да.
Если вы вставляете, что многие записи и вставки довольно упрощены, вы должны посмотреть, как делать Bulk Inserts и вытаскивать ORM.
Ответ 5
Самый быстрый способ вставить записи - это сгенерировать текстовый файл и использовать синтаксис LOAD FILE. Большинство баз данных имеют чрезвычайно быструю реализацию для импорта файлов данных в базы данных. Для MySQL см. Ниже:
http://dev.mysql.com/doc/refman/5.1/en/load-data.html
Для других баз данных обратитесь к соответствующему руководству. Это полезно, если вы вставляете миллион записей или тысячи записей. В противном случае лучше всего создать большой SQL с 1000 вставками и выполнить их непосредственно в вашем подключении к базе данных, пропуская ORM и связанные с ними проверки.