Improve average block time query

This change limits the results that Postgres uses to evaluate the
window. Only `WHERE`, `HAVING`, and `GROUP BY` are used to constrain an
`OVER` (not `LIMIT`), so the change to the subquery in the `FROM` clause
effectively limits the result set to the number of blocks to include in
the average result plus one.

We could also use the (timestamp of the most recent + the timestamp of
the oldest block) / the count of records returned, but that query
requires casts from interval to integer and back to achieve the same
result. The window query ends up being similar in how it communicates.
pull/336/head
Tim Mecklem 7 years ago
parent 9adad92d71
commit 7bde015bb1
  1. 7
      apps/explorer/lib/explorer/chain/statistics.ex
  2. 11
      apps/explorer/test/explorer/chain/statistics_test.exs

@ -13,10 +13,9 @@ defmodule Explorer.Chain.Statistics do
@average_time_query """
SELECT coalesce(avg(difference), interval '0 seconds')
FROM (
SELECT timestamp - lag(timestamp) over (order by timestamp) as difference
FROM blocks
ORDER BY number DESC
LIMIT 100
SELECT b.timestamp - lag(b.timestamp) over (order by b.timestamp) as difference
FROM (SELECT * FROM blocks ORDER BY number DESC LIMIT 101) b
LIMIT 100 OFFSET 1
) t
"""

@ -27,11 +27,14 @@ defmodule Explorer.Chain.StatisticsTest do
assert Timex.diff(statistics.timestamp, time, :seconds) == 0
end
test "returns the average time between blocks" do
test "returns the average time between blocks for the last 100 blocks" do
time = DateTime.utc_now()
next_time = Timex.shift(time, seconds: 5)
insert(:block, timestamp: time)
insert(:block, timestamp: next_time)
insert(:block, timestamp: Timex.shift(time, seconds: -1000))
for x <- 100..0 do
insert(:block, timestamp: Timex.shift(time, seconds: -5 * x))
end
assert %Statistics{
average_time: %Duration{

Loading…
Cancel
Save