我有一个在 PostgreSQL 9.3 上创建的包含 100k 行的表
create table demo_bbb
(
id numeric NOT NULL,
code_bbb character varying,
column_02 character varying,
column_03 character varying,
column_04 character varying,
column_05 character varying,
column_06 character varying,
column_07 character varying,
column_08 character varying,
column_09 character varying,
column_10 character varying,
CONSTRAINT demo_bbb_pk PRIMARY KEY (id)
);
这是我的测试(每个查询运行 3 次):
(1) select id from demo_bbb b ; -- database query time: ~26ms
(2) select column_10 from demo_bbb b ; -- database query time: 46ms, 48ms, 51ms
(3) select column_05 from demo_bbb b ; -- database query time: 37ms, 38 ms, 45ms
(4) select * from demo_bbb b ; -- database query time: 28ms, 32ms, 37ms
结果: (4) 的平均时间 < (2)、(3) 的时间(32ms < 45 ms)
解释分析:
(1) "Seq Scan on demo_bbb b (cost=0.00..4425.00 rows=100000 width=6) (actual time=0.008..22.088 rows=100000 loops=1)"
(2) "Seq Scan on demo_bbb b (cost=0.00..4425.00 rows=100000 width=24) (actual time=0.008..38.702 rows=100000 loops=1)"
(3) "Seq Scan on demo_bbb b (cost=0.00..4425.00 rows=100000 width=24) (actual time=0.008..32.098 rows=100000 loops=1)"
(4) "Seq Scan on demo_bbb b (cost=0.00..4425.00 rows=100000 width=232) (actual time=0.007..17.702 rows=100000 loops=1)"
我很想知道发生了什么,但我无法理解。你能给我解释一下这些查询是如何进行的吗?
注意:我使用 SQL Profiler (从 Enterprisedb 下载)跟踪了这些查询
几乎是 WAG,因为您还没有显示
EXPLAIN (BUFFERS, OUTPUT)
数据,但是:如果您使用的是 9.2 或更高版本,这可能会对用于实现主键约束的唯一索引进行仅索引扫描。鉴于后者是最有可能的情况;如果它完成了 seqscan(就像在旧版本上那样),您将从以后的查询中获得更快的结果。
这些可能会进行 seqscans,并且可能会进行离线 TOAST 提取。
不同的时间部分是由于缓存的影响,部分原因可能是当您选择更多列时需要读取更多的外联 TOAST 数据。
PostgreSQL 使用两级缓存——操作系统的磁盘缓存和它自己的
shared_buffers
. 两者都是块缓存。它没有查询结果缓存。有关更多信息,请参阅 PostgreSQL 手册和有关 PostgreSQL 基准测试、调整、缓存行为等的现有资源。