【发布时间】:2020-01-21 02:57:20
【问题描述】:
我有一张表accounts 和索引
accounts {
id text
num_id bigint
pid text
fid text
created_at timestamp with time zone
updated_at timestamp with time zone
}
CREATE UNIQUE INDEX accounts_pkey ON public.accounts USING btree (id)
CREATE INDEX fid_idx ON public.accounts USING btree (fid)
CREATE INDEX idx_accounts_pid_fid ON public.accounts USING btree (pid, fid)
而且这个查询很慢
explain analyse SELECT * FROM accounts
WHERE pid = 'hd' AND fid = '123'
ORDER BY id ASC
LIMIT 1;
Limit (cost=0.56..3173.34 rows=1 width=123) (actual time=49389.351..49389.351 rows=0 loops=1)
-> Index Scan using accounts_pkey on accounts (cost=0.56..5022497.13 rows=1583 width=123) (actual time=49389.350..49389.350 rows=0 loops=1)
Filter: ((pid = 'hd'::text) AND (fid = '123'::text))
Rows Removed by Filter: 56821193
Planning time: 0.094 ms
Execution time: 49389.368 ms
根据这个answer,可以通过添加不需要的where条件pid和fid来解决
explain analyse SELECT * FROM accounts
WHERE pid = 'hd' AND fid = '123'
ORDER BY id ASC, pid, fid
LIMIT 1;
但是,它不起作用
Limit (cost=0.56..3173.37 rows=1 width=123) (actual time=49495.236..49495.236 rows=0 loops=1)
-> Index Scan using accounts_pkey on accounts (cost=0.56..5022556.07 rows=1583 width=123) (actual time=49495.234..49495.234 rows=0 loops=1)
Filter: ((pid = 'hd'::text) AND (fid = '123'::text))
Rows Removed by Filter: 56821555
Planning time: 0.096 ms
Execution time: 49495.253 ms
我是不是不见了?
PostgreSQL 版本:9.6.8
【问题讨论】:
-
只是好奇,
SELECT * FROM accounts ORDER BY id LIMIT 1的运行时间是多少? -
@TimBiegeleisen,
SELECT * FROM accounts ORDER BY id LIMIT 1的运行时间是Limit (cost=0.56..0.65 rows=1 width=123) (actual time=0.010..0.010 rows=1 loops=1) -> Index Scan using accounts_pkey on accounts (cost=0.56..4738719.60 rows=56980788 width=123) (actual time=0.010..0.010 rows=1 loops=1) Planning time: 0.078 ms Execution time: 0.027 ms -
我在下面尝试了一个答案,希望能部分解释你所看到的。我不知道为什么 Postgres 会选择这个执行计划,但是索引定义的轻微变化可能会解决所有问题。
标签: postgresql performance limit