簡體   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