[英]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_analyze
和last_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 收集的統計量,如下所述。
當我們UPDATE
和DELETE
數據將創建一個可能存在於堆或索引中但我們無法查詢的死元組時, VACUUM
可以幫助我們回收被死元組占用的存儲。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.