PostgreSQL。优化从大 table 中检索不同的值
Postgresql. Optimize retriving distinct values from large table
我有一个具有 40 多列(约 150 万行,1 Gb)的非规范化 table。
CREATE TABLE tbl1 (
...
division_id integer,
division_name varchar(10),
...
);
我需要加快查询速度
SELECT DISTINCT division_name, division_id
FROM table
ORDER BY division_name;
仅查询 return 约 250 行,但非常慢,因为大小为 table。
我已尝试创建索引:
create index idx1 on tbl1 (division_name, division_id)
但当前执行计划:
explain analyze SELECT Distinct division_name, division_id FROM tbl1 ORDER BY 1;
QUERY PLAN
-----------------------------------------------------------------
Sort (cost=143135.77..143197.64 rows=24748 width=74) (actual time=1925.697..1925.723 rows=294 loops=1)
Sort Key: division_name
Sort Method: quicksort Memory: 74kB
-> HashAggregate (cost=141082.30..141329.78 rows=24748 width=74) (actual time=1923.853..1923.974 rows=294 loops=1)
Group Key: division_name, division_id
-> Seq Scan on tbl1 (cost=0.00..132866.20 rows=1643220 width=74) (actual time=0.069..703.008 rows=1643220 loops=1)
Planning time: 0.311 ms
Execution time: 1925.883 ms
有什么建议为什么索引不起作用或我如何以其他方式加快查询速度?
服务器 Postgresql 9.6.
p.s。是的,table 有 40 多列并且是去规范化的,但我知道所有关于 with decision 的利弊。
更新1
@a_horse_with_no_name 建议使用 vacuum analyze 而不是 analyze 来更新 table 统计信息。现在查询 plain 是:
QUERY PLAN
------------------------
Unique (cost=0.55..115753.43 rows=25208 width=74) (actual time=0.165..921.426 rows=294 loops=1)
-> Index Only Scan using idx1 on tbl1 (cost=0.55..107538.21 rows=1643044 width=74) (actual time=0.162..593.322 rows=1643220 loops=1)
Heap Fetches: 0
好多了!
索引可能只有在 PostgreSQL 选择“仅索引扫描”时才有帮助,这意味着它根本不需要查看 table 数据。
通常 PostgreSQL 必须检查 table 数据(“堆”)以查看行是否对当前事务可见,因为可见性信息未存储在索引中。
但是,如果 table 没有太大变化并且最近被 VACUUM
ed,PostgreSQL 知道大多数页面只包含对每个人可见的项目(有一个“可见性”地图”以跟踪该信息),然后扫描索引可能更便宜。
在 table 上尝试 运行 VACUUM
,看看是否会导致使用仅索引扫描。
除此之外,没有办法加快这样的查询。
我有一个具有 40 多列(约 150 万行,1 Gb)的非规范化 table。
CREATE TABLE tbl1 (
...
division_id integer,
division_name varchar(10),
...
);
我需要加快查询速度
SELECT DISTINCT division_name, division_id
FROM table
ORDER BY division_name;
仅查询 return 约 250 行,但非常慢,因为大小为 table。
我已尝试创建索引:
create index idx1 on tbl1 (division_name, division_id)
但当前执行计划:
explain analyze SELECT Distinct division_name, division_id FROM tbl1 ORDER BY 1;
QUERY PLAN
-----------------------------------------------------------------
Sort (cost=143135.77..143197.64 rows=24748 width=74) (actual time=1925.697..1925.723 rows=294 loops=1)
Sort Key: division_name
Sort Method: quicksort Memory: 74kB
-> HashAggregate (cost=141082.30..141329.78 rows=24748 width=74) (actual time=1923.853..1923.974 rows=294 loops=1)
Group Key: division_name, division_id
-> Seq Scan on tbl1 (cost=0.00..132866.20 rows=1643220 width=74) (actual time=0.069..703.008 rows=1643220 loops=1)
Planning time: 0.311 ms
Execution time: 1925.883 ms
有什么建议为什么索引不起作用或我如何以其他方式加快查询速度?
服务器 Postgresql 9.6.
p.s。是的,table 有 40 多列并且是去规范化的,但我知道所有关于 with decision 的利弊。
更新1
@a_horse_with_no_name 建议使用 vacuum analyze 而不是 analyze 来更新 table 统计信息。现在查询 plain 是:
QUERY PLAN
------------------------
Unique (cost=0.55..115753.43 rows=25208 width=74) (actual time=0.165..921.426 rows=294 loops=1)
-> Index Only Scan using idx1 on tbl1 (cost=0.55..107538.21 rows=1643044 width=74) (actual time=0.162..593.322 rows=1643220 loops=1)
Heap Fetches: 0
好多了!
索引可能只有在 PostgreSQL 选择“仅索引扫描”时才有帮助,这意味着它根本不需要查看 table 数据。
通常 PostgreSQL 必须检查 table 数据(“堆”)以查看行是否对当前事务可见,因为可见性信息未存储在索引中。
但是,如果 table 没有太大变化并且最近被 VACUUM
ed,PostgreSQL 知道大多数页面只包含对每个人可见的项目(有一个“可见性”地图”以跟踪该信息),然后扫描索引可能更便宜。
在 table 上尝试 运行 VACUUM
,看看是否会导致使用仅索引扫描。
除此之外,没有办法加快这样的查询。