bur*_*nsy 8 postgresql index aggregate index-tuning postgresql-9.4
有没有办法索引以下查询?
SELECT run_id, MAX ( frame ) , MAX ( time ) FROM run.frames_stat GROUP BY run_id;
Run Code Online (Sandbox Code Playgroud)
我尝试在frame
and上创建排序(非复合)索引time
,并在 上创建索引run_id
,但查询规划器不使用它们。
杂项信息:
frames_stat
表有 4200 万行架构:
CREATE TABLE run.frame_stat (
id bigint NOT NULL,
run_id bigint NOT NULL,
frame bigint NOT NULL,
heap_size bigint NOT NULL,
"time" timestamp without time zone NOT NULL,
CONSTRAINT frame_stat_pkey PRIMARY KEY (id)
)
Run Code Online (Sandbox Code Playgroud)
解释分析:
HashAggregate (cost=1086240.000..1086242.800 rows=280 width=24) (actual time=14182.426..14182.545 rows=280 loops=1)
Group Key: run_id
-> Seq Scan on zulu (cost=0.000..770880.000 rows=42048000 width=24) (actual time=0.037..4077.182 rows=42048000 loops=1)
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 10
如果您根本无法更改查询,那就太糟糕了。你不会得到很好的解决方案。如果您没有对表 ( ) 进行表限定,您可以在另一个模式(或只是一个临时模式)中创建一个具有相同名称的物化视图(见下文)并调整(可选地仅在需要的会话中) -获得卓越的性能。run.
frames_stat
search_path
这是这种技术的秘诀:
@ Joishi的想法有RULE
会(绝望),最后不得已的措施。但我宁愿不去那里。意外行为的陷阱太多。
如果您可以更改查询,您应该尝试模拟松散索引扫描:
当基于每个相关一行run_id
的单独表时,这甚至更有效- 我们称之为run_tbl
。如果您还没有它,请创建它!
使用相关子查询实现:
SELECT run_id
, (SELECT frame
FROM run.frames_stat
WHERE run_id = r.run_id
ORDER BY frame DESC NULLS LAST
LIMIT 1) AS max_frame
, (SELECT "time"
FROM run.frames_stat
WHERE run_id = r.run_id
ORDER BY "time" DESC NULLS LAST
LIMIT 1) AS max_time
FROM run_tbl r;
Run Code Online (Sandbox Code Playgroud)
创建两个多列索引与匹配排序闪电的性能:
CREATE index fun_frame_idx ON run.frames_stat (run_id, frame DESC NULLS LAST);
CREATE index fun_frame_idx ON run.frames_stat (run_id, "time" DESC NULLS LAST);
Run Code Online (Sandbox Code Playgroud)
NULLS LAST
只有在可以有空值时才需要。但它不会伤害任何方式。
只有 280 个 distinct run_id
,这将非常快。
或者,基于这些关键信息:
“frames_stat”表有 4200 万行
rows=280 -- 返回的行数=distinct run_id
表格不变(无插入/删除)
使用 a MATERIALIZED VIEW
,它将很小(只有 280 行)并且速度非常快。
您仍然需要更改查询以使其基于 MV 而不是表。
旁白:永远不要使用(在标准 SQL 中)这样的保留字time
作为标识符。
归档时间: |
|
查看次数: |
13032 次 |
最近记录: |