【问题标题】:How to optimize a MAX SQL query with GROUP BY DATE如何使用 GROUP BY DATE 优化 MAX SQL 查询
【发布时间】:2018-03-09 03:35:58
【问题描述】:

我正在尝试从具有 3M 行的表中优化查询。

这些列是valuedatetimepoint_id

SELECT DATE(datetime), MAX(value) FROM historical_points WHERE point_id=1 GROUP BY DATE(datetime);

此查询需要 2 秒。

我尝试索引point_id=1,但结果并没有好多少。

是否可以索引MAX 查询,或者有更好的方法吗?也许有一个 INNER JOIN?

编辑: 这是类似的解释分析,即更好地解决问题。这个也有性能问题。

EXPLAIN ANALYZE SELECT DATE(datetime), MAX(value), MIN(value) FROM buildings_hispoint WHERE point_id=64 AND datetime BETWEEN '2017-09-01 00:00:00' AND '2017-10-01 00:00:00' GROUP BY DATE(datetime);
>GroupAggregate(成本=84766.65..92710.99 行=336803 宽度=68)(实际时间=1461.060..2701.145 行=21 循环=1) > 组键:(日期(日期时间)) > -> 排序(成本=84766.65..85700.23 行=373430 宽度=14)(实际时间=1408.445..1547.929 行=523621 循环=1) > 排序键:(日期(日期时间)) > 排序方法:外部排序磁盘:11944kB > -> 在buildings_hispoint 上的位图堆扫描(成本=10476.02..43820.81 行=373430 宽度=14)(实际时间=148.970..731.154 行=523621 循环=1) > 重新检查条件:(point_id = 64) > 过滤器: ((datetime >= '2017-09-01 00:00:00+02'::timestamp with time zone) AND (datetime Rows Removed by Filter: 35712 > 堆块:精确=14422 > -> 在buildings_measurementdatapoint_ffb10c68 上的位图索引扫描(成本=0.00..10382.67 行=561898 宽度=0)(实际时间=125.150..125.150 行=559333 循环=1) > 索引条件:(point_id = 64) >规划时间:0.284 ms >执行时间:2704.566 ms

【问题讨论】:

  • 你有日期时间的索引吗?
  • 可能听起来很奇怪,但是一个覆盖索引可以将 (point_id, datetime, value) 优化为单个索引。
  • 我们需要查看您的表和索引定义。
  • 提供您当前的解释分析

标签: sql postgresql


【解决方案1】:

没有看到EXPLAIN的输出很难说什么。我的猜测是您必须在索引定义中包含DATE() 调用:

CREATE INDEX historical_points_idx ON historical_points (DATE(datetime), point_id);

另外,如果point_id 的不同值比DATE(datetime) 更多,那么您必须颠倒列顺序:

CREATE INDEX historical_points_idx ON historical_points (point_id, DATE(datetime));

请记住,列的基数对规划者非常重要,优先选择具有高选择性的列。

【讨论】:

  • 我试过: CREATE INDEX history_points_idx ON history_points (DATE(datetime AT TIME ZONE 'UTC'), point_id);但它没有任何区别
【解决方案2】:
SELECT DISTINCT ON (DATE(datetime)) DATE(datetime), value 
FROM historical_points WHERE point_id=1
ORDER BY DATE(datetime) DESC, value DESC;

DATE(datetime), value 上放置一个计算索引。 [我希望那些不是你真正的列名。使用像 VALUE 这样的保留字作为列名会造成混淆。]

SELECT DISTINCT 将像GROUP ON 一样工作。 ORDER BY 替换了 MAX,如果被索引会很快。

我将这项技术归功于@ErwinBrandstetter。

【讨论】:

  • 这有点快,但不是很多。老实说,我不知道我能把它推倒多少。您认为进一步减少它看起来可行吗?
  • 你的索引是什么。这应该运行得很快。
猜你喜欢
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
相关资源
最近更新 更多