【发布时间】:2015-07-31 19:48:48
【问题描述】:
我有一个简单的表,其中包含名为 id 的单列 PRIMARY KEY,输入 serial。那里正好有 100,000,000 行。表占用 48GB,PK 索引 ca 2,1GB。运行的机器仅适用于 Postgres,它类似于 Core i5、500GB HDD、8GB RAM。 Pg 配置由 pgtune 实用程序创建(共享缓冲区 ca 2GB,有效缓存 ca 7GB)。操作系统是 Ubuntu 服务器 14.04,Postgres 9.3.6。
为什么SELECT count(id) 和SELECT count(*) 在这种简单的情况下都这么慢(大约 11 分钟)?
为什么 PostgreSQL 规划器选择全表扫描而不是索引扫描,它应该至少快 25 倍(在它必须从 HDD 读取整个索引的情况下)。或者我哪里错了?
顺便说一句,连续多次运行查询并没有改变任何东西。仍然 cca 11 分钟。
执行计划在这里:
Aggregate (cost=7500001.00..7500001.01 rows=1 width=0) (actual time=698316.978..698316.979 rows=1 loops=1)
Buffers: shared hit=192 read=6249809
-> Seq Scan on transaction (cost=0.00..7250001.00 rows=100000000 width=0) (actual time=0.009..680594.049 rows=100000001 loops=1)
Buffers: shared hit=192 read=6249809
Total runtime: 698317.044 ms
【问题讨论】:
-
要读取的数据量要小 25 倍,并且包含所有足以计数的键,不是吗?我已经运行了 VACUUM FULL 和 ANALYZE (顺便说一句,总共花了 6 个多小时)。
-
你有很多并发 DML 发生在那个表上吗?只有在可靠的情况下才能(并且将)使用该索引。如果有很多并发事务(或未完成的事务),那么 Postgres 可能不会选择使用索引。您是否有修改该表的“事务中的空闲”连接?还有
random_page_cost(postgresql.org/docs/current/static/…) 的值是多少,该设置会影响规划者使用索引的倾向。 -
您可能还想阅读以下内容:wiki.postgresql.org/wiki/Index-only_scans
标签: sql postgresql select postgresql-9.3