summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorStan Hu <stanhu@gmail.com>2018-11-04 05:59:13 -0800
committerStan Hu <stanhu@gmail.com>2018-11-04 06:01:17 -0800
commit5c8ce94052fab07c979f6b1ecef9f7b807909b94 (patch)
treeffe0a839038dc2accdae13a7fc6d7b763861f2b4 /app
parent4d3ff28a6a0d81f44ccb3eb1602996e5d7c3de1c (diff)
downloadgitlab-ce-5c8ce94052fab07c979f6b1ecef9f7b807909b94.tar.gz
Fix statement timeouts in RemoveRestrictedTodos migration
On GitLab.com, the RemoveRestrictedTodos background migration encountered about 700+ failures a day due to statement timeouts. PostgreSQL might perform badly with a LIMIT 1 because the planner is guessing that scanning the index in ID order will come across the desired row in less time it will take the planner than using another index. The order_hint does not affect the search results. For example, `ORDER BY id ASC, updated_at ASC` means the same thing as `ORDER BY id ASC`. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/52649
Diffstat (limited to 'app')
-rw-r--r--app/models/concerns/each_batch.rb17
1 files changed, 15 insertions, 2 deletions
diff --git a/app/models/concerns/each_batch.rb b/app/models/concerns/each_batch.rb
index 8cf0b8b154d..6314b46a7e3 100644
--- a/app/models/concerns/each_batch.rb
+++ b/app/models/concerns/each_batch.rb
@@ -39,7 +39,15 @@ module EachBatch
#
# of - The number of rows to retrieve per batch.
# column - The column to use for ordering the batches.
- def each_batch(of: 1000, column: primary_key)
+ # order_hint - An optional column to append to the `ORDER BY id`
+ # clause to help the query planner. PostgreSQL might perform badly
+ # with a LIMIT 1 because the planner is guessing that scanning the
+ # index in ID order will come across the desired row in less time
+ # it will take the planner than using another index. The
+ # order_hint does not affect the search results. For example,
+ # `ORDER BY id ASC, updated_at ASC` means the same thing as `ORDER
+ # BY id ASC`.
+ def each_batch(of: 1000, column: primary_key, order_hint: nil)
unless column
raise ArgumentError,
'the column: argument must be set to a column name to use for ordering rows'
@@ -48,7 +56,9 @@ module EachBatch
start = except(:select)
.select(column)
.reorder(column => :asc)
- .take
+
+ start = start.order(order_hint) if order_hint
+ start = start.take
return unless start
@@ -60,6 +70,9 @@ module EachBatch
.select(column)
.where(arel_table[column].gteq(start_id))
.reorder(column => :asc)
+
+ stop = stop.order(order_hint) if order_hint
+ stop = stop
.offset(of)
.limit(1)
.take