Skip to content

Commit e63deae

Browse files
committed
Make sure we're using indexes during rollbacks
Fixes #2083 The `queryMinRefId` query uses ```sql SELECT id FROM <table> WHERE <field> >= $1 ORDER BY id ASC LIMIT 1. ``` The planner sometimes picks a bad plan: ```sql Index Scan using tx_pkey on tx Filter: (block_id >= $1) ``` the filter is not Index Cond, so this ends up in a sequential scan. The index refers to the primary key and is only used for sorting. Instead we use a simpler query without ORDER BY: SELECT id FROM <table> WHERE <field> >= $1 LIMIT 10000 This forces the planner to use the field's index. The results are fetched and the minimum is found in Haskell. Near the tip this returns only a handful of rows. If there are more than 10000 matching rows (large rollback), we fall back to the original ORDER BY id ASC LIMIT 1 query.
1 parent cb61094 commit e63deae

1 file changed

Lines changed: 41 additions & 2 deletions

File tree

  • cardano-db/src/Cardano/Db/Operations

cardano-db/src/Cardano/Db/Operations/Query.hs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,45 @@ queryMinRefId ::
581581
field ->
582582
ReaderT SqlBackend m (Maybe (Key record))
583583
queryMinRefId txIdField txId = do
584+
res <- select $ do
585+
rec <- from $ table @record
586+
where_ (rec ^. txIdField >=. val txId)
587+
limit 10000
588+
pure $ rec ^. persistIdField
589+
if length res >= 10000
590+
then queryMinRefIdFallback txIdField txId
591+
else pure $ minimumMay $ map unValue res
592+
where
593+
minimumMay [] = Nothing
594+
minimumMay xs = Just (minimum xs)
595+
596+
queryMinRefIdNullable ::
597+
forall m field record.
598+
(MonadIO m, PersistEntity record, PersistField field) =>
599+
EntityField record (Maybe field) ->
600+
field ->
601+
ReaderT SqlBackend m (Maybe (Key record))
602+
queryMinRefIdNullable txIdField txId = do
603+
res <- select $ do
604+
rec <- from $ table @record
605+
where_ (isJust (rec ^. txIdField))
606+
where_ (rec ^. txIdField >=. just (val txId))
607+
limit 10000
608+
pure $ rec ^. persistIdField
609+
if length res >= 10000
610+
then queryMinRefIdNullableFallback txIdField txId
611+
else pure $ minimumMay $ map unValue res
612+
where
613+
minimumMay [] = Nothing
614+
minimumMay xs = Just (minimum xs)
615+
616+
queryMinRefIdFallback ::
617+
forall m field record.
618+
(MonadIO m, PersistEntity record, PersistField field) =>
619+
EntityField record field ->
620+
field ->
621+
ReaderT SqlBackend m (Maybe (Key record))
622+
queryMinRefIdFallback txIdField txId = do
584623
res <- select $ do
585624
rec <- from $ table @record
586625
where_ (rec ^. txIdField >=. val txId)
@@ -589,13 +628,13 @@ queryMinRefId txIdField txId = do
589628
pure $ rec ^. persistIdField
590629
pure $ unValue <$> listToMaybe res
591630

592-
queryMinRefIdNullable ::
631+
queryMinRefIdNullableFallback ::
593632
forall m field record.
594633
(MonadIO m, PersistEntity record, PersistField field) =>
595634
EntityField record (Maybe field) ->
596635
field ->
597636
ReaderT SqlBackend m (Maybe (Key record))
598-
queryMinRefIdNullable txIdField txId = do
637+
queryMinRefIdNullableFallback txIdField txId = do
599638
res <- select $ do
600639
rec <- from $ table @record
601640
where_ (isJust (rec ^. txIdField))

0 commit comments

Comments
 (0)