NHibernate:在同一会话中保存不同类型的对象会中断批处理 [英] NHibernate: Saving different types of objects in the same session breaks batching

查看:168
本文介绍了NHibernate:在同一会话中保存不同类型的对象会中断批处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



看起来在同一个会话中断不同类型的对象会造成批量分配,导致显着的性能下降。 (100),但不幸的是同样的问题,Test1()仍然比Test2慢5倍左右()):

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


$ / code $ / pre

AdoNetBatchSize被设置为1000:

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

这些是模型:

{
public virtual int Id {get;私人设置}
}

public class TestClass2
{
public virtual int Id {get;私人设置}
}

这些是测试方法。 Test1()需要62秒,Test2()只需要11秒(正如Phill建议的,我尝试了无状态的会话,但不幸的是同样的问题):

  [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();



$ b [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();
使用(var session = Session.BeginTransaction())
使用(var session = SessionFactory.OpenSession())
{
}

{
for(int i = 0; i< count; i ++)
{
var y = new TestClass2();
session.Save(y);
}
transaction.Commit();





$ p

有什么想法?



谢谢!

更新:

测试项目可以从此处下载。 。您需要在Main方法中更改connectionString。我把所有的会话都改成了无状态会话。



我的restuls:Test1 = 59.11,Test2 = 7.60,Test3 = 7.72。 Test1比Test2& Test3!

解决方案

当您运行test2和test3时,插入的是一起批处理的。 $ b

当您运行test1时,在替换插入的位置,插入将作为单独的语句发出,并且不会一起批处理。



我发现通过分析所有三个测试发现了这一点。

根据Diego的回答,它必须保留我写了第四个测试,我把批量大小设置为10,然后交替,当我从TestClass1更改为TestClass2所以我做了5个TestClass1,然后是5个TestClass2,来达到批量大小。
$ b

这个按批次处理的顺序推出了5个批次。

 public void Test4()
{
int count = 10;
using(var session = SessionFactory.OpenSession())
using(var transaction = session.BeginTransaction())
{
for(int i = 0; i {
var x = new TestClass1();
session.Save(x);




for(int j = 0; j <5; j ++)
{
var y =新的TestClass2();
session.Save(y);



transaction.Commit();

}



然后我将它改为每次插入3 5.批次的数量是3的倍数,所以必须发生的是批量的大小允许1批量的批量达到指定的数量,但是只能将相同的类型组合在一起。交替导致单独的插入语句。


newbie here, sorry if this is an obvious question.

It seems saving different types of objects in the same session breaks batching, cause significant performance drop.

ID generator is set to Increment (as Diego Mijelshon advised, I tried hilo("100"), but unfortunately same issue, Test1() is still about 5 times slower than Test2()):

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

AdoNetBatchSize is set to 1000:

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

These are the models:

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

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

These are the test methods. Test1() takes 62 seconds, Test2() takes only 11 seconds. (as Phill advised, I tried stateless sessions, but unfortunately same issue):

    [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();
            }
        }
    }

Any ideas?

Thanks!

Update:

The test project can be downloaded from here. You need to change the connectionString in the Main method. I changed all sessions to stateless sessions.

My restuls: Test1 = 59.11, Test2 = 7.60, Test3 = 7.72. Test1 is 7.7 times slower than Test2 & Test3!

解决方案

When you run test2 and test3, the insert's are batched together.

When you run test1, where you alternate the inserts, the inserts are issued as separate statements and are not batched together.

I found this out by profiling all three tests.

So as per Diego's answer, it must preserve the order that you're inserting, and batch them together.

I wrote a 4th test, I set the batch size to 10, then alternated when i changed from TestClass1 to TestClass2 so that I was doing 5 of TestClass1 and then 5 of TestClass2, to hit the batch size.

This pushed out batch's of 5 in the order they were processed.

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();
    }
}

Then I changed it to insert 3 at a time instead of 5. The batch's were in multiples of 3, so what must be happening is the batch size allows a batch of 1 type to go to specified amount, but groups only the same type together. While alternating causes separate insert statements.

这篇关于NHibernate:在同一会话中保存不同类型的对象会中断批处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆