postgresql - PostgreSQL 慢命令
问题描述
我在 PostgreSQL 13.1 上有表(超过 1 亿条记录)
CREATE TABLE report
(
id serial primary key,
license_plate_id integer,
datetime timestamp
);
索引(为了测试我创建了它们):
create index report_lp_datetime_index on report (license_plate_id, datetime);
create index report_lp_datetime_desc_index on report (license_plate_id desc, datetime desc);
所以,我的问题是为什么查询像
select * from report r
where r.license_plate_id in (1,2,4,5,6,7,8,10,15,22,34,75)
order by datetime desc
limit 100
非常慢(~10 秒)。但是没有订单语句的查询很快(毫秒)。
解释:
explain (analyze, buffers, format text) select * from report r
where r.license_plate_id in (1,2,4,5,6,7,8,10,15,22,34, 75,374,57123)
limit 100
Limit (cost=0.57..400.38 rows=100 width=316) (actual time=0.037..0.216 rows=100 loops=1)
Buffers: shared hit=103
-> Index Scan using report_lp_id_idx on report r (cost=0.57..44986.97 rows=11252 width=316) (actual time=0.035..0.202 rows=100 loops=1)
Index Cond: (license_plate_id = ANY ('{1,2,4,5,6,7,8,10,15,22,34,75,374,57123}'::integer[]))
Buffers: shared hit=103
Planning Time: 0.228 ms
Execution Time: 0.251 ms
explain (analyze, buffers, format text) select * from report r
where r.license_plate_id in (1,2,4,5,6,7,8,10,15,22,34,75,374,57123)
order by datetime desc
limit 100
Limit (cost=44193.63..44193.88 rows=100 width=316) (actual time=4921.030..4921.047 rows=100 loops=1)
Buffers: shared hit=11455 read=671
-> Sort (cost=44193.63..44221.76 rows=11252 width=316) (actual time=4921.028..4921.035 rows=100 loops=1)
Sort Key: datetime DESC
Sort Method: top-N heapsort Memory: 128kB
Buffers: shared hit=11455 read=671
-> Bitmap Heap Scan on report r (cost=151.18..43763.59 rows=11252 width=316) (actual time=54.422..4911.927 rows=12148 loops=1)
Recheck Cond: (license_plate_id = ANY ('{1,2,4,5,6,7,8,10,15,22,34,75,374,57123}'::integer[]))
Heap Blocks: exact=12063
Buffers: shared hit=11455 read=671
-> Bitmap Index Scan on report_lp_id_idx (cost=0.00..148.37 rows=11252 width=0) (actual time=52.631..52.632 rows=12148 loops=1)
Index Cond: (license_plate_id = ANY ('{1,2,4,5,6,7,8,10,15,22,34,75,374,57123}'::integer[]))
Buffers: shared hit=59 read=4
Planning Time: 0.427 ms
Execution Time: 4921.128 ms
解决方案
如果从磁盘读取 671 个 8kB 块需要几秒钟,您的存储似乎相当慢。
加快这个速度的方法是按照与索引相同的方式对表进行重新排序,以便您可以在相同或相邻的表块中找到所需的行:
CLUSTER report_lp_id_idx USING report_lp_id_idx;
请注意,以这种方式重写表会导致停机 - 表在重写时将不可用。而且PostgreSQL不维护表的顺序,所以后续的数据修改会导致性能逐渐变差,过一段时间又得CLUSTER
重新运行。
但是,如果您无论如何都需要快速查询此查询,那么CLUSTER
就是要走的路。
推荐阅读
- ios - 无法在核心数据中订购自定义对象
- reactjs - React router 6,使用Navigate如何获取路径名
- python - 通过 Python 发送电子邮件
- javascript - 如何在 DHTMLX 甘特图中添加父栏并仅使用 javascript 刷新特定的父栏
- c - c中字符串和字符数组之间的长度差异?
- java - 尝试在空对象引用上调用虚拟方法“(java.lang.String)”
- javascript - Javascript 中的饼图无法正常工作
- flutter - Flutter Search Delegate 过滤数据,首字母大写
- typescript - 如何在打字稿中制作一种类型的函数链(数组)?
- ios - SwiftUI如何在TextField中选择文本