NHibernate: сохранение разных типов объектов в одном сеансе прерывает пакетную обработку - PullRequest
1 голос
/ 16 февраля 2011

новичок здесь, извините, если это очевидный вопрос.

Кажется, сохранение разных типов объектов в одной и той же сессии прерывает пакет, вызывает значительное снижение производительности.

Генератор идентификаторов установлен наПриращение (как советовал Диего Миджелсон, я пробовал hilo («100»), но, к сожалению, та же проблема, Test1 () все еще примерно в 5 раз медленнее, чем Test2 ()):

public class CustomIdConvention : IIdConvention
{
    public void Apply(IIdentityInstance instance)
    {
        instance.GeneratedBy.Increment();
    }
}

AdoNetBatchSize установлен в 1000:

MsSqlConfiguration.MsSql2008
.ConnectionString(connectionString)
.AdoNetBatchSize(1000)
.Cache(x => x
    .UseQueryCache()
    .ProviderClass<HashtableCacheProvider>())
.ShowSql();

Это модели:

public class TestClass1
{
    public virtual int Id { get; private set; }
}

public class TestClass2
{
    public virtual int Id { get; private set; }
}

Это методы испытаний. Test1 () занимает 62 секунды, Test2 () занимает всего 11 секунд. (как советовал Фил, я пробовал сеансы без сохранения состояния, но, к сожалению, та же проблема):

    [TestMethod]
    public void Test1()
    {
        int count = 50 * 1000;
        using (var session = SessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                for (int i = 0; i < count; i++)
                {
                    var x = new TestClass1();
                    var y = new TestClass2();
                    session.Save(x);
                    session.Save(y);
                }
                transaction.Commit();
            }
        }
    }

    [TestMethod]
    public void Test2()
    {
        int count = 50 * 1000;
        using (var session = SessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                for (int i = 0; i < count; i++)
                {
                    var x = new TestClass1();
                    session.Save(x);
                }
                transaction.Commit();
            }
        }
        using (var session = SessionFactory.OpenSession())
        {
            using (var transaction = session.BeginTransaction())
            {
                for (int i = 0; i < count; i++)
                {
                    var y = new TestClass2();
                    session.Save(y);
                }
                transaction.Commit();
            }
        }
    }

Есть идеи?

Спасибо!

Обновление:

Тестовый проект можно загрузить с здесь .Вам нужно изменить connectionString в методе Main.Я изменил все сеансы на сеансы без сохранения состояния.

Мои рестулы: Test1 = 59,11, Test2 = 7,60, Test3 = 7,72.Тест1 в 7,7 раза медленнее, чем Тест2 и Тест3!

Ответы [ 2 ]

0 голосов
/ 16 февраля 2011

Когда вы запускаете test2 и test3, вставки объединяются вместе.

Когда вы запускаете test1, где вы чередуете вставки, вставки выдаются как отдельные операторы и не объединяются вместе.

Я выяснил это, профилировав все три теста.

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

Я написал 4-й тест, я установил размер пакета на 10, а затем изменил его, когда я изменил с TestClass1 на TestClass2, чтобы я делал 5 из TestClass1 и затем 5 из TestClass2, чтобы достичь размера пакета.вытолкнул партии из 5 в порядке их обработки.public void Test4() { int count = 10; using (var session = SessionFactory.OpenSession()) using (var transaction = session.BeginTransaction()) { for (int i = 0; i < count; i++) { if (i%2 == 0) { for (int j = 0; j < 5; j++) { var x = new TestClass1(); session.Save(x); } } else { for (int j = 0; j < 5; j++) { var y = new TestClass2(); session.Save(y); } } } transaction.Commit(); } }

Затем я изменил его на вставку 3 за раз вместо 5. Пакеты были кратны 3, поэтому должно происходить то, что размер партии позволяет партии 1 типа перейти к указанномуколичество, но группирует только один и тот же тип вместе.При чередовании вызывает отдельные операторы вставки.

0 голосов
/ 16 февраля 2011

Не используйте приращение. Это худший из возможных генераторов.

Попробуйте изменить его на HiLo.

Обновление:

Похоже, что проблема возникает, когда чередование сохраняет различных объектов, независимо от того, разделены сеанс / транзакция или нет.

Это дает результаты, аналогичные второму методу испытаний:

[TestMethod]
public void Test3()
{
    int count = 50 * 1000;
    using (var session = SessionFactory.OpenSession())
    {
        using (var transaction = session.BeginTransaction())
        {
            for (int i = 0; i < count; i++)
            {
                var x = new TestClass1();
                session.Save(x);
            }
            for (int i = 0; i < count; i++)
            {
                var y = new TestClass2();
                session.Save(y);
            }
            transaction.Commit();
        }
    }
}

Мое предположение, не смотря на источники NH, состоит в том, что он сохраняет порядок из-за возможных отношений между сущностями, даже когда их нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...