-
Notifications
You must be signed in to change notification settings - Fork 14
Improve journal delete performance #538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -115,22 +115,37 @@ public async Task<IImmutableList<Exception>> AsyncWriteMessages( | |
| public async Task Delete(string persistenceId, long maxSequenceNr, CancellationToken cancellationToken) | ||
| { | ||
| using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ShutdownToken); | ||
| long maxMarkedDeletion; | ||
|
|
||
| // no need to use transaction | ||
| await using (var connection = ConnectionFactory.GetConnection()) | ||
| { | ||
| maxMarkedDeletion = await MaxMarkedForDeletionMaxPersistenceIdQuery(connection, persistenceId, maxSequenceNr).FirstOrDefaultAsync(cts.Token); | ||
| } | ||
|
|
||
| if (maxMarkedDeletion is 0) | ||
| return; | ||
|
Comment on lines
+126
to
+127
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Early bail out condition, just return if there's nothing to delete. |
||
|
|
||
| await ConnectionFactory.ExecuteWithTransactionAsync( | ||
| WriteIsolationLevel, | ||
| cts.Token, | ||
| async (connection, token) => | ||
| { | ||
| await connection | ||
| .GetTable<JournalRow>() | ||
| var journalTable = connection.GetTable<JournalRow>(); | ||
| await journalTable | ||
| .Where( | ||
| r => | ||
| r.PersistenceId == persistenceId && | ||
| r.SequenceNumber <= maxSequenceNr) | ||
| r.SequenceNumber == maxMarkedDeletion) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of marking all of the records less than the requested sequence number as deleted, we mark the highest affected instead. Update 1 record instead of many. |
||
| .Set(r => r.Deleted, true) | ||
| .UpdateAsync(token); | ||
|
|
||
| var maxMarkedDeletion = | ||
| await MaxMarkedForDeletionMaxPersistenceIdQuery(connection, persistenceId).FirstOrDefaultAsync(token); | ||
| await journalTable | ||
| .Where( | ||
| r => | ||
| r.PersistenceId == persistenceId && | ||
| r.SequenceNumber < maxMarkedDeletion) | ||
| .DeleteAsync(token); | ||
|
Comment on lines
+143
to
+148
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Simplify the deletion query, just delete anything that is less than the highest affected row. |
||
|
|
||
| if (JournalConfig.DaoConfig.SqlCommonCompatibilityMode) | ||
| { | ||
|
|
@@ -149,19 +164,7 @@ await connection | |
| SequenceNumber = maxMarkedDeletion, | ||
| }, | ||
| token: token); | ||
| } | ||
|
|
||
| await connection | ||
| .GetTable<JournalRow>() | ||
| .Where( | ||
| r => | ||
| r.PersistenceId == persistenceId && | ||
| r.SequenceNumber <= maxSequenceNr && | ||
| r.SequenceNumber < maxMarkedDeletion) | ||
| .DeleteAsync(token); | ||
|
|
||
| if (JournalConfig.DaoConfig.SqlCommonCompatibilityMode) | ||
| { | ||
| await connection | ||
| .GetTable<JournalMetaData>() | ||
| .Where( | ||
|
|
@@ -177,7 +180,7 @@ await connection | |
| .GetTable<JournalTagRow>() | ||
| .Where( | ||
| r => | ||
| r.SequenceNumber <= maxSequenceNr && | ||
| r.SequenceNumber < maxMarkedDeletion && | ||
| r.PersistenceId == persistenceId) | ||
| .DeleteAsync(token); | ||
| } | ||
|
|
@@ -442,10 +445,11 @@ protected static ImmutableList<Exception> BuildWriteRejections(List<Util.Try<Jou | |
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| private static IQueryable<long> MaxMarkedForDeletionMaxPersistenceIdQuery( | ||
| AkkaDataConnection connection, | ||
| string persistenceId) | ||
| string persistenceId, | ||
| long maxSequenceNr) | ||
| => connection | ||
| .GetTable<JournalRow>() | ||
| .Where(r => r.PersistenceId == persistenceId && r.Deleted) | ||
| .Where(r => r.PersistenceId == persistenceId && r.SequenceNumber <= maxSequenceNr) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optimization, instead of checking against persistence id and deleted field, check against persistence id and sequence number instead, as they are indexed. |
||
| .OrderByDescending(r => r.SequenceNumber) | ||
| .Select(r => r.SequenceNumber) | ||
| .Take(1); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add missing retry policy factory check. The
Factory(if not null) is used internally by Linq2Db to populateDataConnection.RetryPolicyif theDataOption.RetryPolicyOptions.RetryPolicyis null.