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