@@ -84,8 +84,71 @@ class TExecuteWriteUnit : public TExecutionUnit {
84
84
return false ;
85
85
}
86
86
87
- EExecutionStatus OnTabletNotReadyException (TDataShardUserDb& userDb, TWriteOperation& writeOp, TTransactionContext& txc, const TActorContext& ctx) {
87
+ void FillOps (const NTable::TScheme& scheme, const TUserTable& userTable, const NTable::TScheme::TTableInfo& tableInfo, const TValidatedWriteTxOperation& validatedOperation, ui32 rowIdx, TSmallVec<NTable::TUpdateOp>& ops) {
88
+ const TSerializedCellMatrix& matrix = validatedOperation.GetMatrix ();
89
+ const auto & columnIds = validatedOperation.GetColumnIds ();
90
+
91
+ ops.clear ();
92
+ Y_ENSURE (matrix.GetColCount () >= userTable.KeyColumnIds .size ());
93
+ ops.reserve (matrix.GetColCount () - userTable.KeyColumnIds .size ());
94
+
95
+ for (ui16 valueColIdx = userTable.KeyColumnIds .size (); valueColIdx < matrix.GetColCount (); ++valueColIdx) {
96
+ ui32 columnTag = columnIds[valueColIdx];
97
+ const TCell& cell = matrix.GetCell (rowIdx, valueColIdx);
98
+
99
+ const NScheme::TTypeId vtypeId = scheme.GetColumnInfo (&tableInfo, columnTag)->PType .GetTypeId ();
100
+ ops.emplace_back (columnTag, NTable::ECellOp::Set, cell.IsNull () ? TRawTypeValue () : TRawTypeValue (cell.Data (), cell.Size (), vtypeId));
101
+ }
102
+ };
103
+
104
+ void FillKey (const NTable::TScheme& scheme, const TUserTable& userTable, const NTable::TScheme::TTableInfo& tableInfo, const TValidatedWriteTxOperation& validatedOperation, ui32 rowIdx, TSmallVec<TRawTypeValue>& key) {
105
+ const TSerializedCellMatrix& matrix = validatedOperation.GetMatrix ();
106
+
107
+ key.clear ();
108
+ key.reserve (userTable.KeyColumnIds .size ());
109
+ for (ui16 keyColIdx = 0 ; keyColIdx < userTable.KeyColumnIds .size (); ++keyColIdx) {
110
+ const TCell& cell = matrix.GetCell (rowIdx, keyColIdx);
111
+ ui32 keyCol = tableInfo.KeyColumns [keyColIdx];
112
+ if (cell.IsNull ()) {
113
+ key.emplace_back ();
114
+ } else {
115
+ NScheme::TTypeId vtypeId = scheme.GetColumnInfo (&tableInfo, keyCol)->PType .GetTypeId ();
116
+ key.emplace_back (cell.Data (), cell.Size (), vtypeId);
117
+ }
118
+ }
119
+ };
120
+
121
+ EExecutionStatus OnTabletNotReadyException (TDataShardUserDb& userDb, TWriteOperation& writeOp, size_t operationIndexToPrecharge, TTransactionContext& txc, const TActorContext& ctx) {
88
122
LOG_TRACE_S (ctx, NKikimrServices::TX_DATASHARD, " Tablet " << DataShard.TabletID () << " is not ready for " << writeOp << " execution" );
123
+
124
+ // Precharge
125
+ if (operationIndexToPrecharge != SIZE_MAX) {
126
+ const TValidatedWriteTx::TPtr& writeTx = writeOp.GetWriteTx ();
127
+ for (size_t operationIndex = operationIndexToPrecharge; operationIndex < writeTx->GetOperations ().size (); ++operationIndex) {
128
+ const TValidatedWriteTxOperation& validatedOperation = writeTx->GetOperations ()[operationIndex];
129
+ const ui64 tableId = validatedOperation.GetTableId ().PathId .LocalPathId ;
130
+ const TTableId fullTableId (DataShard.GetPathOwnerId (), tableId);
131
+ const TUserTable& userTable = *DataShard.GetUserTables ().at (tableId);
132
+
133
+ const NTable::TScheme& scheme = txc.DB .GetScheme ();
134
+ const NTable::TScheme::TTableInfo& tableInfo = *scheme.GetTableInfo (userTable.LocalTid );
135
+
136
+ const TSerializedCellMatrix& matrix = validatedOperation.GetMatrix ();
137
+ const auto operationType = validatedOperation.GetOperationType ();
138
+
139
+ TSmallVec<TRawTypeValue> key;
140
+
141
+ if (operationType == NKikimrDataEvents::TEvWrite::TOperation::OPERATION_INSERT ||
142
+ operationType == NKikimrDataEvents::TEvWrite::TOperation::OPERATION_UPDATE ||
143
+ userDb.NeedToReadBeforeWrite (fullTableId))
144
+ {
145
+ for (ui32 rowIdx = 0 ; rowIdx < matrix.GetRowCount (); ++rowIdx) {
146
+ FillKey (scheme, userTable, tableInfo, validatedOperation, rowIdx, key);
147
+ userDb.PrechargeRow (fullTableId, key);
148
+ }
149
+ }
150
+ }
151
+ }
89
152
90
153
DataShard.IncCounter (COUNTER_TX_TABLET_NOT_READY);
91
154
@@ -109,51 +172,28 @@ class TExecuteWriteUnit : public TExecutionUnit {
109
172
const TUserTable& userTable = *DataShard.GetUserTables ().at (tableId);
110
173
111
174
const NTable::TScheme& scheme = txc.DB .GetScheme ();
112
- const NTable::TScheme::TTableInfo* tableInfo = scheme.GetTableInfo (userTable.LocalTid );
113
-
114
- TSmallVec<TRawTypeValue> key;
115
- TSmallVec<NTable::TUpdateOp> ops;
175
+ const NTable::TScheme::TTableInfo& tableInfo = *scheme.GetTableInfo (userTable.LocalTid );
116
176
117
177
const TSerializedCellMatrix& matrix = validatedOperation.GetMatrix ();
118
178
const auto operationType = validatedOperation.GetOperationType ();
119
179
120
- auto fillOps = [&](ui32 rowIdx) {
121
- ops.clear ();
122
- Y_ABORT_UNLESS (matrix.GetColCount () >= userTable.KeyColumnIds .size ());
123
- ops.reserve (matrix.GetColCount () - userTable.KeyColumnIds .size ());
124
-
125
- for (ui16 valueColIdx = userTable.KeyColumnIds .size (); valueColIdx < matrix.GetColCount (); ++valueColIdx) {
126
- ui32 columnTag = validatedOperation.GetColumnIds ()[valueColIdx];
127
- const TCell& cell = matrix.GetCell (rowIdx, valueColIdx);
180
+ TSmallVec<TRawTypeValue> key;
181
+ TSmallVec<NTable::TUpdateOp> ops;
128
182
129
- const NScheme::TTypeId vtypeId = scheme.GetColumnInfo (tableInfo, columnTag)->PType .GetTypeId ();
130
- ops.emplace_back (columnTag, NTable::ECellOp::Set, cell.IsNull () ? TRawTypeValue () : TRawTypeValue (cell.Data (), cell.Size (), vtypeId));
131
- }
132
- };
183
+ // Main update cycle
133
184
134
185
for (ui32 rowIdx = 0 ; rowIdx < matrix.GetRowCount (); ++rowIdx)
135
186
{
136
- key.clear ();
137
- key.reserve (userTable.KeyColumnIds .size ());
138
- for (ui16 keyColIdx = 0 ; keyColIdx < userTable.KeyColumnIds .size (); ++keyColIdx) {
139
- const TCell& cell = matrix.GetCell (rowIdx, keyColIdx);
140
- ui32 keyCol = tableInfo->KeyColumns [keyColIdx];
141
- if (cell.IsNull ()) {
142
- key.emplace_back ();
143
- } else {
144
- NScheme::TTypeId vtypeId = scheme.GetColumnInfo (tableInfo, keyCol)->PType .GetTypeId ();
145
- key.emplace_back (cell.Data (), cell.Size (), vtypeId);
146
- }
147
- }
187
+ FillKey (scheme, userTable, tableInfo, validatedOperation, rowIdx, key);
148
188
149
189
switch (operationType) {
150
190
case NKikimrDataEvents::TEvWrite::TOperation::OPERATION_UPSERT: {
151
- fillOps ( rowIdx);
191
+ FillOps (scheme, userTable, tableInfo, validatedOperation, rowIdx, ops );
152
192
userDb.UpsertRow (fullTableId, key, ops);
153
193
break ;
154
194
}
155
195
case NKikimrDataEvents::TEvWrite::TOperation::OPERATION_REPLACE: {
156
- fillOps ( rowIdx);
196
+ FillOps (scheme, userTable, tableInfo, validatedOperation, rowIdx, ops );
157
197
userDb.ReplaceRow (fullTableId, key, ops);
158
198
break ;
159
199
}
@@ -162,12 +202,12 @@ class TExecuteWriteUnit : public TExecutionUnit {
162
202
break ;
163
203
}
164
204
case NKikimrDataEvents::TEvWrite::TOperation::OPERATION_INSERT: {
165
- fillOps ( rowIdx);
205
+ FillOps (scheme, userTable, tableInfo, validatedOperation, rowIdx, ops );
166
206
userDb.InsertRow (fullTableId, key, ops);
167
207
break ;
168
208
}
169
209
case NKikimrDataEvents::TEvWrite::TOperation::OPERATION_UPDATE: {
170
- fillOps ( rowIdx);
210
+ FillOps (scheme, userTable, tableInfo, validatedOperation, rowIdx, ops );
171
211
userDb.UpdateRow (fullTableId, key, ops);
172
212
break ;
173
213
}
@@ -177,6 +217,8 @@ class TExecuteWriteUnit : public TExecutionUnit {
177
217
}
178
218
}
179
219
220
+ // Counters
221
+
180
222
switch (operationType) {
181
223
case NKikimrDataEvents::TEvWrite::TOperation::OPERATION_UPSERT:
182
224
case NKikimrDataEvents::TEvWrite::TOperation::OPERATION_REPLACE:
@@ -216,6 +258,7 @@ class TExecuteWriteUnit : public TExecutionUnit {
216
258
}
217
259
218
260
const TValidatedWriteTx::TPtr& writeTx = writeOp->GetWriteTx ();
261
+ size_t validatedOperationIndex = SIZE_MAX;
219
262
220
263
DataShard.ReleaseCache (*writeOp);
221
264
@@ -360,12 +403,13 @@ class TExecuteWriteUnit : public TExecutionUnit {
360
403
361
404
KqpCommitLocks (tabletId, kqpLocks, sysLocks, writeVersion, userDb);
362
405
363
- TValidatedWriteTx::TPtr& writeTx = writeOp->GetWriteTx ();
364
406
if (writeTx->HasOperations ()) {
365
- for (const auto & validatedOperation : writeTx->GetOperations ()) {
407
+ for (validatedOperationIndex = 0 ; validatedOperationIndex < writeTx->GetOperations ().size (); ++validatedOperationIndex) {
408
+ const TValidatedWriteTxOperation& validatedOperation = writeTx->GetOperations ()[validatedOperationIndex];
366
409
DoUpdateToUserDb (userDb, validatedOperation, txc);
367
410
LOG_DEBUG_S (ctx, NKikimrServices::TX_DATASHARD, " Executed write operation for " << *writeOp << " at " << DataShard.TabletID () << " , row count=" << validatedOperation.GetMatrix ().GetRowCount ());
368
411
}
412
+ validatedOperationIndex = SIZE_MAX;
369
413
} else {
370
414
LOG_DEBUG_S (ctx, NKikimrServices::TX_DATASHARD, " Skip empty write operation for " << *writeOp << " at " << DataShard.TabletID ());
371
415
}
@@ -451,7 +495,7 @@ class TExecuteWriteUnit : public TExecutionUnit {
451
495
}
452
496
return EExecutionStatus::Continue;
453
497
} catch (const TNotReadyTabletException&) {
454
- return OnTabletNotReadyException (userDb, *writeOp, txc, ctx);
498
+ return OnTabletNotReadyException (userDb, *writeOp, validatedOperationIndex, txc, ctx);
455
499
} catch (const TLockedWriteLimitException&) {
456
500
userDb.ResetCollectedChanges ();
457
501
0 commit comments