postgresql - 优化具有多个最小和最大范围的 SQL 查询

标签 postgresql optimization

我在优化 SQL 查询时遇到了大问题,该查询需要很长时间才能在一组大约 300,000 行的数据上运行。

我正在包含十进制 value 和日期时间 recorded_at 列的 stat_records 表上运行查询。

我想找出以下任意时间段内的 MAX 和 MIN 值:所有时间、去年、过去 6 个月、过去 3 个月、上个月、过去 2 周。

我现在的做法是针对上面指定的每个时间间隔单独运行以下 SQL 查询:

SELECT MIN("stat_records"."value")
FROM "stat_records"
   INNER JOIN "stats" ON "stats"."id" = "stat_records"."stat_id"
WHERE "stat_records"."object_id" = $1
  AND "stats"."identifier" = $2
  AND ("stat_records"."recorded_at" BETWEEN $3 AND $4)

[["object_id", 1],
 ["identifier", "usd"],
 ["recorded_at", "2018-10-15 20:10:58.418512"],
 ["recorded_at", "2018-12-15 20:11:59.351437"]]

表定义为:

create_table "stat_records", force: :cascade do |t|
  t.datetime "recorded_at"
  t.decimal "value"
  t.bigint "coin_id"
  t.bigint "object_id"
  t.index ["object_id"], name: "index_stat_records_on_object_id"
  t.index ["recorded_at", "object_id", "stat_id"], name: "for_upsert", unique: true
  t.index ["recorded_at", "stat_id"], name: "index_stat_records_on_recorded_at_and_stat_id", unique: true
  t.index ["recorded_at"], name: "index_stat_records_on_recorded_at"
  t.index ["stat_id"], name: "index_stat_records_on_stat_id"
  t.index ["value"], name: "index_stat_records_on_value"
end

然而,这种方法需要很长时间才能完成。我在 stat_records 表的 valuerecorded_at 列上都有索引。

我在这里缺少什么 - 我应该做什么来优化它?

也许有一些更好的方法,我可以执行 1 个查询,并让 postgres 为我进行优化。

最佳答案

索引只能加速需要表的较小部分(或排序)的查询。因此,您永远不能指望索引能够使整个时间范围内的查询更快。

您的解决方案可以是物化 View 。这样,您可以预先聚合值,并且生成的表会小得多,因此查询速度会更快。缺点是物化 View 需要定期刷新,并且其间包含稍微陈旧的数据。

一个例子:

CREATE MATERIALIZED VIEW stats_per_month AS
SELECT stat_records.object_id, 
       stats.identifier
       date_trunc('month', stat_records.recorded_at) AS recorded_month,
       min(stat_records.value) AS minval
FROM stat_records
   INNER JOIN stats ON stats.id = stat_records.stat_id
GROUP BY stat_records.object_id, 
         stats.identifier
         date_trunc('month', stat_records.recorded_at);

如果您的查询需要月份粒度,您只需从物化 View 而不是原始表中查询即可。

您还可以使用混合解决方案,并对小范围使用原始查询,其中过时的数据可能会造成更大的伤害。使用 recorded_at 上的索引应该会很快。

关于postgresql - 优化具有多个最小和最大范围的 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53797134/

相关文章:

ruby-on-rails-3 - PGError : Error: column of relation does not exist

python - 在列表列表中搜索列表的快速方法

C++:在最后优化时计算零

javascript - 如何在 IE 7 和 6 等浏览器中复制类似于 querySelector 的内容?

mysql - MySQL 是否比 PostgreSQL(在 Perl/DBI 下)更能抵抗 SQL 注入(inject)攻击?

java - Hibernate 实体中的 Postgres 数组

postgresql - 新的 Heroku pg :backups public-url provide? 是什么类型的文件

Mysql查询优化

c - 是否可以用 C 编写零成本的异常处理?

postgresql - 删除唯一约束 - PostgreSQL