返回 Discover
Field DispatchStack Overflow9 · 2026-05-31

Why does my query insist on a full table scan?

Tags
postgresqlquery-optimization
Score
1
Answers
7
Views
83
Answered
Yes
痛点分析发布于 2026/05/30

痛点为 AI 基于上游原始证据的初步提炼;未包含额外中国市场检索。

痛点

用户在PostgreSQL中按日期字段journeyTime对表进行分区,期望查询优化器能利用分区裁剪仅扫描相关分区,但实际执行了全表扫描。原因是WHERE子句中使用了date_trunc函数包裹分区键,导致优化器无法识别分区键的原始值,从而无法进行分区裁剪。这造成了查询性能严重下降,尤其是在数据量大的表上,全表扫描会消耗大量I/O和CPU资源,增加查询响应时间,影响应用的整体效率。用户需要手动调整查询写法,将条件改为范围比较才能利用分区特性,增加了开发和维护成本。

§ Dossier

Stack Overflow question

I have a PostgreSQL table partitioned by a datetime field called journeyTime . If I have a query where the selection criteria is... WHERE date_trunc('day', journeyTime) = '01-May-2025' I would expect the explain plan to show that the query optimiser has immediately zoomed in on the single partition that all the records for that date are in. It doesn't. Instead it does a full table scan on all partitions in the table. Why?

§ Dossier

Question details

View count
83
Answer count
7
Last activity
2026/05/30
§ Dossier

Answers

PostgreSQL can only perform partition pruning if the WHERE clause contains a comparison with the partitioning key : one side of the comparison operator must be the plain partitioning key. Burying it inside a function call or other expression won't work. Assuming that journeytime is a timestamp with time zone and your days begin and end according to UTC, your WHERE condition should be: WHERE journeytime >= TIMESTAMP WITH TIME ZONE '2025-05-01 00:00:00 UTC' AND journeytime < TIMESTAMP WITH TIME ZONE '2025-05-01 00:00:00 UTC' + INTERVAL '1 day'

评论作者信息不可用3 votes

Has many characteristics of being AI generated - which is not allowed on this site.

评论作者信息不可用1 votes

How about you show us the explain plan so we can see? (But the other answer is probably correct - but will likely get deleted since it looks to be AI generated). Also it appears you want a concrete answer, if so, why ask it as an open-ended question for discussion?

评论作者信息不可用1 votes
源数据· Raw Archive
source
Stack Overflow
upstream_source
stackoverflow
upstream_item_id
79948253
daily_ranking_item_id
e4fdbe09-92e8-449c-b548-47d1afa4a6ae
rank_date
2026-05-31
rank
9
name
Why does my query insist on a full table scan?
tagline
postgresql, query-optimization
description
I have a PostgreSQL table partitioned by a datetime field called journeyTime . If I have a query where the selection criteria is... WHERE date_trunc('day', journeyTime) = '01-May-2025' I would expect the explain plan to show that the query optimiser has immediately zoomed in on the single partition that all the records for that date are in. It doesn't. Instead it does a full table scan on all partitions in the table. Why?
votes_count
1
comments_count
7
created_at_on_source
2026-05-29T05:02:49.000Z
topics
postgresqlquery-optimization
media / source-specific data
{
  "stackoverflow": {
    "score": 1,
    "view_count": 83,
    "is_answered": true,
    "top_answers": [
      {
        "body": "PostgreSQL can only perform partition pruning if the WHERE clause contains a comparison with the partitioning key : one side of the comparison operator must be the plain partitioning key. Burying it inside a function call or other expression won't work. Assuming that journeytime is a timestamp with time zone and your days begin and end according to UTC, your WHERE condition should be: WHERE journeytime >= TIMESTAMP WITH TIME ZONE '2025-05-01 00:00:00 UTC' AND journeytime < TIMESTAMP WITH TIME ZONE '2025-05-01 00:00:00 UTC' + INTERVAL '1 day'",
        "score": 3,
        "answer_id": 79948284,
        "is_accepted": false
      },
      {
        "body": "Has many characteristics of being AI generated - which is not allowed on this site.",
        "score": 1,
        "answer_id": 79948266,
        "is_accepted": false
      },
      {
        "body": "How about you show us the explain plan so we can see? (But the other answer is probably correct - but will likely get deleted since it looks to be AI generated). Also it appears you want a concrete answer, if so, why ask it as an open-ended question for discussion?",
        "score": 1,
        "answer_id": 79948267,
        "is_accepted": false
      }
    ],
    "answer_count": 7,
    "accepted_answer_id": null,
    "last_activity_date": 1780167265
  }
}
raw_payload
{
  "stats": {
    "score": 1,
    "view_count": 83,
    "is_answered": true,
    "answer_count": 7,
    "creation_date": 1780030969,
    "last_edit_date": 1780033323,
    "accepted_answer_id": null,
    "last_activity_date": 1780167265
  },
  "api_wrapper": {
    "backoff": null,
    "has_more": true,
    "page_size": 8,
    "quota_max": 300,
    "quota_remaining": 206
  },
  "question_id": 79948253,
  "answer_fetch": {
    "has_more": true,
    "answers_fetched": 3,
    "answer_page_size": 3
  },
  "snapshot_version": "stackoverflow_question_v1"
}
source_raw_snapshot
{
  "id": "4434b2f7-ca71-4d35-9264-ae1c4abe12c1",
  "daily_ranking_item_id": "e4fdbe09-92e8-449c-b548-47d1afa4a6ae",
  "source": "stackoverflow",
  "external_id": "79948253",
  "fetched_at": "2026-05-30T22:02:04.421Z",
  "question_raw": {
    "body": "<p>I have a PostgreSQL table partitioned by a datetime field called <em>journeyTime</em>.</p>\n<p>If I have a query where the selection criteria is...</p>\n<pre><code>WHERE date_trunc('day', journeyTime) = '01-May-2025'\n</code></pre>\n<p>I would expect the <em><strong>explain plan</strong></em> to show that the query optimiser has immediately zoomed in on the single partition that all the records for that date are in.</p>\n<p>It doesn't. Instead it does a full table scan on all partitions in the table.</p>\n<p>Why?</p>\n",
    "link": "https://stackoverflow.com/questions/79948253/why-does-my-query-insist-on-a-full-table-scan",
    "tags": [
      "postgresql",
      "query-optimization"
    ],
    "owner": {
      "link": "https://stackoverflow.com/users/8424293/conanthegerbil",
      "user_id": 8424293,
      "user_type": "registered",
      "account_id": 11494454,
      "reputation": 867,
      "display_name": "ConanTheGerbil",
      "profile_image": "https://www.gravatar.com/avatar/d3d03e1d5302f3a749902d8bcd2e069b?s=256&d=identicon&r=PG&f=y&so-version=2"
    },
    "score": 1,
    "title": "Why does my query insist on a full table scan?",
    "view_count": 83,
    "is_answered": true,
    "question_id": 79948253,
    "answer_count": 7,
    "creation_date": 1780030969,
    "last_edit_date": 1780033323,
    "content_license": "CC BY-SA 4.0",
    "last_activity_date": 1780167265
  },
  "answers_raw": [
    {
      "body": "<p>PostgreSQL can only perform <em>partition pruning</em> if the <code>WHERE</code> clause contains a comparison with the <em>partitioning key</em>: one side of the comparison operator must be the plain partitioning key. Burying it inside a function call or other expression won't work.</p>\n<p>Assuming that <code>journeytime</code> is a <code>timestamp with time zone</code> and your days begin and end according to UTC, your <code>WHERE</code> condition should be:</p>\n<pre><code>WHERE journeytime &gt;= TIMESTAMP WITH TIME ZONE '2025-05-01 00:00:00 UTC'\n  AND journeytime &lt; TIMESTAMP WITH TIME ZONE '2025-05-01 00:00:00 UTC' + INTERVAL '1 day'\n</code></pre>\n",
      "owner": {
        "link": "https://stackoverflow.com/users/6464308/laurenz-albe",
        "user_id": 6464308,
        "user_type": "registered",
        "account_id": 8633322,
        "reputation": 259685,
        "display_name": "Laurenz Albe",
        "profile_image": "https://i.sstatic.net/12PVX.jpg?s=256"
      },
      "score": 3,
      "answer_id": 79948284,
      "is_accepted": false,
      "question_id": 79948253,
      "creation_date": 1780034864,
      "content_license": "CC BY-SA 4.0",
      "last_activity_date": 1780034864
    },
    {
      "body": "<p>Has many characteristics of being AI generated - which is not allowed on this site.</p>\n",
      "owner": {
        "link": "https://stackoverflow.com/users/1127428/dale-k",
        "user_id": 1127428,
        "user_type": "registered",
        "account_id": 1144312,
        "reputation": 28358,
        "accept_rate": 79,
        "display_name": "Dale K",
        "profile_image": "https://i.sstatic.net/pSzU4.jpg?s=256"
      },
      "score": 1,
      "answer_id": 79948266,
      "is_accepted": false,
      "question_id": 79948253,
      "creation_date": 1780033200,
      "content_license": "CC BY-SA 4.0",
      "last_activity_date": 1780033200
    },
    {
      "body": "<p>How about you show us the explain plan so we can see? (But the other answer is probably correct - but will likely get deleted since it looks to be AI generated).</p>\n<p>Also it appears you want a concrete answer, if so, why ask it as an open-ended question for discussion?</p>\n",
      "owner": {
        "link": "https://stackoverflow.com/users/1127428/dale-k",
        "user_id": 1127428,
        "user_type": "registered",
        "account_id": 1144312,
        "reputation": 28358,
        "accept_rate": 79,
        "display_name": "Dale K",
        "profile_image": "https://i.sstatic.net/pSzU4.jpg?s=256"
      },
      "score": 1,
      "answer_id": 79948267,
      "is_accepted": false,
      "question_id": 79948253,
      "creation_date": 1780033261,
      "last_edit_date": 1780040103,
      "content_license": "CC BY-SA 4.0",
      "last_activity_date": 1780040103
    }
  ],
  "tags_raw": [
    "postgresql",
    "query-optimization"
  ],
  "stats_raw": {
    "score": 1,
    "view_count": 83,
    "is_answered": true,
    "answer_count": 7,
    "creation_date": 1780030969,
    "last_edit_date": 1780033323,
    "accepted_answer_id": null,
    "last_activity_date": 1780167265
  },
  "selection_meta": {
    "site": "stackoverflow",
    "api_wrapper": {
      "backoff": null,
      "has_more": true,
      "page_size": 8,
      "quota_max": 300,
      "quota_remaining": 206
    },
    "answer_fetch": {
      "backoff": null,
      "has_more": true,
      "answers_fetched": 3,
      "quota_remaining": 177,
      "answer_page_size": 3
    },
    "snapshot_version": "stackoverflow_question_v1",
    "selection_strategy": "tag_whitelist_unanswered_high_score_recent_active"
  },
  "created_at": "2026-05-30T22:02:04.686Z",
  "updated_at": "2026-05-30T22:02:04.686Z"
}