繁体   English   中英

Postgres select 查询在具有 1800 万行的表上进行顺序扫描而不是索引扫描

[英]Postgres select query making sequential scan instead of index scan on table with 18 Million rows

我有一个包含近 1800 万行的 postgres 表,我正在尝试运行此查询

select * from answer where submission_id = 5 and deleted_at is NULL;

submission_id 列的表中有一个部分索引。 这是用于创建索引的命令

CREATE INDEX answer_submission_id ON answer USING btree (submission_id) WHERE (deleted_at IS NULL)

这是上面 select 查询的解释分析

Gather  (cost=1000.00..3130124.70 rows=834 width=377) (actual time=7607.568..7610.130 rows=2 loops=1)
  Workers Planned: 2
  Workers Launched: 2
  Buffers: shared hit=2144966 read=3
  I/O Timings: read=6.169
  ->  Parallel Seq Scan on answer  (cost=0.00..3129041.30 rows=348 width=377) (actual time=6501.951..7604.623 rows=1 loops=3)
        Filter: ((deleted_at IS NULL) AND (submission_id = 5))
        Rows Removed by Filter: 62213625
        Buffers: shared hit=2144966 read=3
        I/O Timings: read=6.169
Planning Time: 0.117 ms
Execution Time: 7610.154 ms

理想情况下,它应该选择 answer_submission_id 索引。 但是 postgres 正在进行顺序扫描。

任何帮助都会非常感激

执行计划向我们展示了估计的读取行与实际读取行之间存在偏差。

Postgresql 优化器是一个基于成本的优化器(CBO),查询将从执行计划中以最小的成本执行。

这样错误的统计数据可能会选择错误的执行计划。

有一个链接表示导致查询缓慢的错误统计信息。 为什么 Postgres 中的错误行估计很慢?

首先,我将使用此查询上次搜索last_analyzelast_vacuum

SELECT
  schemaname, relname,
  last_vacuum, last_autovacuum,
  vacuum_count, autovacuum_count,
  last_analyze,last_autoanalyze
FROM pg_stat_user_tables
where relname = 'tablename';

如果您的统计信息有误,我们可以使用ANALYZE "tablename"来帮助我们从表中收集新的统计信息, ANALYZE扫描速度取决于表的大小。

对于大型表,ANALYZE 会随机抽取表内容样本,而不是检查每一行。 这允许在很短的时间内分析非常大的表。 但是请注意,统计信息只是近似值,每次运行 ANALYZE 时都会略有变化,即使实际表内容没有变化。 这可能会导致 EXPLAIN 显示的规划器估计成本发生微小变化。 在极少数情况下,这种不确定性会导致计划者对查询计划的选择在运行 ANALYZE 后发生变化。 为避免这种情况,请提高 ANALYZE 收集的统计量,如下所述。

当我们UPDATEDELETE数据将创建一个可能存在于堆或索引中但我们无法查询的死元组时, VACUUM可以帮助我们回收被死元组占用的存储。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM