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'
痛点为 AI 基于上游原始证据的初步提炼;未包含额外中国市场检索。
用户在 PostgreSQL 中按日期字段分区后,使用 date_trunc 函数进行查询,期望优化器能直接定位到相关分区,但实际却触发了全表扫描。核心痛点是分区剪枝(partition pruning)无法作用于包裹在函数调用中的分区键,导致查询性能严重下降。用户原本想通过分区表加速按天查询,却因为对优化器行为理解不足而遭遇意外的高延迟和资源浪费。这种摩擦在数据量大的场景下尤为明显,可能造成查询响应时间从毫秒级退化到分钟级,影响业务决策效率,并增加运维排查成本。
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?
Question details
- View count
- 69
- Answer count
- 6
- Last activity
- 2026/05/29
Answers
Has many characteristics of being AI generated - which is not allowed on this site.
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?
源数据· Raw Archive
- source
- Stack Overflow
- upstream_source
- stackoverflow
- upstream_item_id
- 79948253
- daily_ranking_item_id
- ee745c25-2eb9-41f1-822d-0f20cd68a60d
- rank_date
- 2026-05-30
- 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
- 6
- created_at_on_source
- 2026-05-29T05:02:49.000Z
{
"stackoverflow": {
"score": 1,
"view_count": 69,
"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": 6,
"accepted_answer_id": null,
"last_activity_date": 1780069510
}
}{
"stats": {
"score": 1,
"view_count": 69,
"is_answered": true,
"answer_count": 6,
"creation_date": 1780030969,
"last_edit_date": 1780033323,
"accepted_answer_id": null,
"last_activity_date": 1780069510
},
"api_wrapper": {
"backoff": null,
"has_more": true,
"page_size": 8,
"quota_max": 300,
"quota_remaining": 299
},
"question_id": 79948253,
"answer_fetch": {
"has_more": true,
"answers_fetched": 3,
"answer_page_size": 3
},
"snapshot_version": "stackoverflow_question_v1"
}{
"id": "3e9d21e3-b428-4032-afe7-ebfc99958778",
"daily_ranking_item_id": "ee745c25-2eb9-41f1-822d-0f20cd68a60d",
"source": "stackoverflow",
"external_id": "79948253",
"fetched_at": "2026-05-29T22:02:13.965Z",
"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": 69,
"is_answered": true,
"question_id": 79948253,
"answer_count": 6,
"creation_date": 1780030969,
"last_edit_date": 1780033323,
"content_license": "CC BY-SA 4.0",
"last_activity_date": 1780069510
},
"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 >= TIMESTAMP WITH TIME ZONE '2025-05-01 00:00:00 UTC'\n AND journeytime < 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": 69,
"is_answered": true,
"answer_count": 6,
"creation_date": 1780030969,
"last_edit_date": 1780033323,
"accepted_answer_id": null,
"last_activity_date": 1780069510
},
"selection_meta": {
"site": "stackoverflow",
"api_wrapper": {
"backoff": null,
"has_more": true,
"page_size": 8,
"quota_max": 300,
"quota_remaining": 299
},
"answer_fetch": {
"backoff": null,
"has_more": true,
"answers_fetched": 3,
"quota_remaining": 267,
"answer_page_size": 3
},
"snapshot_version": "stackoverflow_question_v1",
"selection_strategy": "tag_whitelist_unanswered_high_score_recent_active"
},
"created_at": "2026-05-29T22:02:14.184Z",
"updated_at": "2026-05-29T22:02:14.184Z"
}