Skip to content

Commit b929502

Browse files
committed
Implement Lazy 2-level multi-row INSERT batches: sizes 16, 256
1 parent a684d7c commit b929502

6 files changed

Lines changed: 47 additions & 22 deletions

File tree

Orm/Xtensive.Orm/Orm/Providers/Interfaces/IPersistDescriptor.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
// Copyright (C) 2012 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2012-2022 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
55
// Created: 2012.03.22
66

7+
using System;
8+
79
namespace Xtensive.Orm.Providers
810
{
911
public interface IPersistDescriptor
1012
{
1113
PersistRequest StoreRequest { get; }
1214

13-
PersistRequest BatchStoreRequest { get; }
15+
Lazy<PersistRequest> LazyLevel1BatchStoreRequest { get; }
16+
Lazy<PersistRequest> LazyLevel2BatchStoreRequest { get; }
1417

1518
PersistRequest ClearRequest { get; }
1619
}

Orm/Xtensive.Orm/Orm/Providers/SqlSessionHandler.IProviderExecutor.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,21 @@ private void Execute(ParameterContext parameterContext)
8585

8686
private void Store(IPersistDescriptor descriptor, IEnumerable<Tuple> tuples)
8787
{
88-
if (descriptor.BatchStoreRequest != null) {
89-
var parametersInBatchStoreRequest = descriptor.BatchStoreRequest.ParameterBindings.Count;
90-
foreach (var chunk in tuples.Chunk(parametersInBatchStoreRequest)) {
91-
if (chunk.Length == parametersInBatchStoreRequest) {
92-
commandProcessor.RegisterTask(new SqlPersistTask(descriptor.BatchStoreRequest, chunk));
88+
if (descriptor.LazyLevel1BatchStoreRequest != null && descriptor.LazyLevel2BatchStoreRequest != null) {
89+
foreach (var level2Chunk in tuples.Chunk(WellKnown.MultiRowInsertLevel2BatchSize)) {
90+
if (level2Chunk.Length == WellKnown.MultiRowInsertLevel2BatchSize) {
91+
commandProcessor.RegisterTask(new SqlPersistTask(descriptor.LazyLevel2BatchStoreRequest.Value, level2Chunk));
9392
}
9493
else {
95-
foreach (var tuple in chunk) {
96-
commandProcessor.RegisterTask(new SqlPersistTask(descriptor.StoreRequest, tuple));
94+
foreach (var level1Chunk in level2Chunk.Chunk(WellKnown.MultiRowInsertLevel1BatchSize)) {
95+
if (level1Chunk.Length == WellKnown.MultiRowInsertLevel1BatchSize) {
96+
commandProcessor.RegisterTask(new SqlPersistTask(descriptor.LazyLevel1BatchStoreRequest.Value, level1Chunk));
97+
}
98+
else {
99+
foreach (var tuple in level1Chunk) {
100+
commandProcessor.RegisterTask(new SqlPersistTask(descriptor.StoreRequest, tuple));
101+
}
102+
}
97103
}
98104
}
99105
}

Orm/Xtensive.Orm/Orm/Providers/TemporaryTables/TemporaryTableDescriptor.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
// Copyright (C) 2003-2010 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2003-2022 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
55
// Created: 2009.11.12
66

7+
using System;
78
using Xtensive.Core;
89

910
using Xtensive.Tuples;
@@ -40,7 +41,12 @@ public sealed class TemporaryTableDescriptor : IPersistDescriptor
4041
/// <summary>
4142
/// Gets or sets the persist request used to store batched data in temporary table.
4243
/// </summary>
43-
public PersistRequest BatchStoreRequest { get; set; }
44+
public Lazy<PersistRequest> LazyLevel1BatchStoreRequest { get; set; }
45+
46+
/// <summary>
47+
/// Gets or sets the persist request used to store batched data in temporary table.
48+
/// </summary>
49+
public Lazy<PersistRequest> LazyLevel2BatchStoreRequest { get; set; }
4450

4551
/// <summary>
4652
/// Gets or sets the persist request used to store data in temporary table.

Orm/Xtensive.Orm/Orm/Providers/TemporaryTables/TemporaryTableManager.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,6 @@ public TemporaryTableDescriptor BuildDescriptor(ModelMapping modelMapping, strin
8484

8585
// insert statements
8686

87-
var batchStoreRequestBindings = new List<PersistParameterBinding>();
88-
var numberOfRecordsInInsert = (int)Math.Sqrt(Handlers.Domain.Configuration.MaxNumberOfConditions);
89-
var batchInsertStatement = MakeUpInsertQuery(tableRef, typeMappings, batchStoreRequestBindings, hasColumns, numberOfRecordsInInsert);
9087

9188
var storeRequestBindings = new List<PersistParameterBinding>();
9289
var insertStatement = MakeUpInsertQuery(tableRef, typeMappings, storeRequestBindings, hasColumns, 1);
@@ -96,16 +93,24 @@ public TemporaryTableDescriptor BuildDescriptor(ModelMapping modelMapping, strin
9693
QueryStatement = queryStatement,
9794
CreateStatement = driver.Compile(SqlDdl.Create(table)).GetCommandText(),
9895
DropStatement = driver.Compile(SqlDdl.Drop(table)).GetCommandText(),
99-
BatchStoreRequest = new PersistRequest(driver, batchInsertStatement, batchStoreRequestBindings),
96+
LazyLevel1BatchStoreRequest = CreateLazyPersistRequest(WellKnown.MultiRowInsertLevel1BatchSize),
97+
LazyLevel2BatchStoreRequest = CreateLazyPersistRequest(WellKnown.MultiRowInsertLevel2BatchSize),
10098
StoreRequest = new PersistRequest(driver, insertStatement, storeRequestBindings),
10199
ClearRequest = new PersistRequest(driver, Handlers.ProviderInfo.Supports(ProviderFeatures.TruncateTable) ? SqlDdl.Truncate(table) : SqlDml.Delete(tableRef), null)
102100
};
103101

104-
result.BatchStoreRequest.Prepare();
105102
result.StoreRequest.Prepare();
106103
result.ClearRequest.Prepare();
107-
108104
return result;
105+
106+
Lazy<PersistRequest> CreateLazyPersistRequest(int batchSize) =>
107+
new Lazy<PersistRequest>(() => {
108+
var bindings = new List<PersistParameterBinding>(batchSize);
109+
var level2BatchInsertStatement = MakeUpInsertQuery(tableRef, typeMappings, bindings, hasColumns, batchSize);
110+
var persistRequest = new PersistRequest(driver, level2BatchInsertStatement, bindings);
111+
persistRequest.Prepare();
112+
return persistRequest;
113+
});
109114
}
110115

111116
/// <summary>

Orm/Xtensive.Orm/Orm/Upgrade/Internals/Metadata/MetadataWriter.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ internal sealed class MetadataWriter
2828
private sealed class Descriptor : IPersistDescriptor
2929
{
3030
public PersistRequest StoreRequest { get; set; }
31-
public PersistRequest BatchStoreRequest { get; }
31+
public Lazy<PersistRequest> LazyLevel1BatchStoreRequest { get; }
32+
public Lazy<PersistRequest> LazyLevel2BatchStoreRequest { get; }
3233
public PersistRequest ClearRequest { get; set; }
3334
}
3435

Orm/Xtensive.Orm/Orm/WellKnown.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ public static partial class WellKnown
8989
/// </summary>
9090
public const int MaxGenericKeyLength = 4;
9191

92+
public const int MultiRowInsertLevel1BatchSize = 16;
93+
94+
public const int MultiRowInsertLevel2BatchSize = 256;
95+
9296
/// <summary>
9397
/// Maximum number of cached keys in <see cref="EntitySetState"/>.
9498
/// </summary>

0 commit comments

Comments
 (0)