mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-13 19:44:21 +00:00
fix(eventstore): order by sequence if filter by aggregate id (#8019)
# Which Problems Are Solved Queriying events by an aggregate id can produce high loads on the database if the aggregate id contains many events (count > 1000000). # How the Problems Are Solved Instead of using the postion and in_tx_order columns we use the sequence column which guarantees correct ordering in a single aggregate and uses more optimised indexes. # Additional Context Closes https://github.com/zitadel/DevOps/issues/50 Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
parent
3e84020065
commit
43404d960c
@ -282,17 +282,23 @@ func (db *CRDB) db() *database.DB {
|
||||
return db.DB
|
||||
}
|
||||
|
||||
func (db *CRDB) orderByEventSequence(desc, useV1 bool) string {
|
||||
func (db *CRDB) orderByEventSequence(desc, shouldOrderBySequence, useV1 bool) string {
|
||||
if useV1 {
|
||||
if desc {
|
||||
return ` ORDER BY event_sequence DESC`
|
||||
}
|
||||
return ` ORDER BY event_sequence`
|
||||
}
|
||||
if shouldOrderBySequence {
|
||||
if desc {
|
||||
return ` ORDER BY "sequence" DESC`
|
||||
}
|
||||
return ` ORDER BY "sequence"`
|
||||
}
|
||||
|
||||
if desc {
|
||||
return ` ORDER BY "position" DESC, in_tx_order DESC`
|
||||
}
|
||||
|
||||
return ` ORDER BY "position", in_tx_order`
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ type querier interface {
|
||||
maxSequenceQuery(useV1 bool) string
|
||||
instanceIDsQuery(useV1 bool) string
|
||||
db() *database.DB
|
||||
orderByEventSequence(desc, useV1 bool) string
|
||||
orderByEventSequence(desc, shouldOrderBySequence, useV1 bool) string
|
||||
dialect.Database
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ func query(ctx context.Context, criteria querier, searchQuery *eventstore.Search
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query, rowScanner := prepareColumns(criteria, q.Columns, useV1)
|
||||
where, values := prepareConditions(criteria, q, useV1)
|
||||
if where == "" || query == "" {
|
||||
@ -78,10 +79,20 @@ func query(ctx context.Context, criteria querier, searchQuery *eventstore.Search
|
||||
q.Desc = true
|
||||
}
|
||||
|
||||
// if there is only one subquery we can optimize the query ordering by ordering by sequence
|
||||
var shouldOrderBySequence bool
|
||||
if len(q.SubQueries) == 1 {
|
||||
for _, filter := range q.SubQueries[0] {
|
||||
if filter.Field == repository.FieldAggregateID {
|
||||
shouldOrderBySequence = filter.Operation == repository.OperationEquals
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch q.Columns {
|
||||
case eventstore.ColumnsEvent,
|
||||
eventstore.ColumnsMaxSequence:
|
||||
query += criteria.orderByEventSequence(q.Desc, useV1)
|
||||
query += criteria.orderByEventSequence(q.Desc, shouldOrderBySequence, useV1)
|
||||
}
|
||||
|
||||
if q.Limit > 0 {
|
||||
@ -220,7 +231,7 @@ func eventsScanner(useV1 bool) func(scanner scan, dest interface{}) (err error)
|
||||
}
|
||||
}
|
||||
|
||||
func prepareConditions(criteria querier, query *repository.SearchQuery, useV1 bool) (string, []any) {
|
||||
func prepareConditions(criteria querier, query *repository.SearchQuery, useV1 bool) (_ string, args []any) {
|
||||
clauses, args := prepareQuery(criteria, useV1, query.InstanceID, query.InstanceIDs, query.ExcludedInstances)
|
||||
if clauses != "" && len(query.SubQueries) > 0 {
|
||||
clauses += " AND "
|
||||
|
Loading…
Reference in New Issue
Block a user