为什么 Postgres Planner 在“输出”部分显示我在查询中不使用的列?

问题描述 投票:0回答:1

我使用 Postgres 15.1 并运行以下查询:

EXPLAIN (ANALYZE, VERBOSE)
WITH segmented_customer AS (SELECT *
                            FROM customer
                            WHERE integration_id = 162
                              AND (1 = 1 OR 1 = 1)),
     segmented_subscription
         AS (SELECT * FROM subscription WHERE integration_id = 162 AND 1 = 1),
     segmented_billing_cycle
         AS (SELECT * FROM billing_cycle WHERE integration_id = 162),
     segmented_product_version
         AS (SELECT * FROM product_version WHERE integration_id = 162 AND 1 = 1)
SELECT segmented_customer.id                         AS customer_id,
       segmented_customer.name                       AS customer_name,
       segmented_subscription.override_start_date    AS sub_override_start_ts,
       segmented_subscription.source_start_date      AS sub_source_start_ts,
       segmented_subscription.override_end_date      AS sub_override_end_ts,
       segmented_subscription.computed_end_date      AS sub_computed_end_ts,
       segmented_product_version.override_mrr_amount AS override_mrr_amount,
       segmented_product_version.total_mrr           AS total_mrr,
       segmented_product_version.version_start_date  AS version_start_ts,
       segmented_product_version.version_end_date    AS version_end_ts
FROM segmented_customer
         JOIN segmented_subscription
              ON segmented_customer.id = segmented_subscription.customer_id
         JOIN segmented_billing_cycle
              ON segmented_subscription.id = segmented_billing_cycle.subscription_id
         JOIN segmented_product_version
              ON segmented_billing_cycle.id = segmented_product_version.billing_cycle_id;

查询计划器显示以下内容:

Gather  (cost=48644.92..114335.21 rows=1 width=105) (actual time=869.975..8133.738 rows=88061 loops=1)
"  Output: customer.id, customer.name, subscription.override_start_date, subscription.source_start_date, subscription.override_end_date, subscription.computed_end_date, product_version.override_mrr_amount, product_version.total_mrr, product_version.version_start_date, product_version.version_end_date"
  Workers Planned: 2
  Workers Launched: 2
  ->  Nested Loop  (cost=47644.92..113335.11 rows=1 width=105) (actual time=799.597..7986.501 rows=29354 loops=3)
"        Output: customer.id, customer.name, subscription.override_start_date, subscription.source_start_date, subscription.override_end_date, subscription.computed_end_date, product_version.override_mrr_amount, product_version.total_mrr, product_version.version_start_date, product_version.version_end_date"
        Worker 0:  actual time=755.136..7930.513 rows=28962 loops=1
          JIT:
            Functions: 29
"            Options: Inlining false, Optimization false, Expressions true, Deforming true"
"            Timing: Generation 5.048 ms, Inlining 0.000 ms, Optimization 0.922 ms, Emission 15.867 ms, Total 21.838 ms"
        Worker 1:  actual time=775.757..7927.262 rows=28968 loops=1
          JIT:
            Functions: 29
"            Options: Inlining false, Optimization false, Expressions true, Deforming true"
"            Timing: Generation 5.482 ms, Inlining 0.000 ms, Optimization 0.897 ms, Emission 16.110 ms, Total 22.489 ms"
        ->  Nested Loop  (cost=47644.49..113256.53 rows=9 width=81) (actual time=776.203..3896.817 rows=27877 loops=3)
"              Output: customer.id, customer.name, subscription.override_start_date, subscription.source_start_date, subscription.override_end_date, subscription.computed_end_date, billing_cycle.id"
              Worker 0:  actual time=730.393..3856.151 rows=27652 loops=1
              Worker 1:  actual time=730.376..3842.788 rows=27320 loops=1
              ->  Parallel Hash Join  (cost=47644.05..105823.47 rows=192 width=81) (actual time=752.267..1282.571 rows=9149 loops=3)
"                    Output: customer.id, customer.name, subscription.override_start_date, subscription.source_start_date, subscription.override_end_date, subscription.computed_end_date, subscription.id"
                    Inner Unique: true
                    Hash Cond: ((subscription.customer_id)::text = (customer.id)::text)
                    Worker 0:  actual time=694.538..1252.813 rows=8950 loops=1
                    Worker 1:  actual time=694.479..1230.973 rows=9024 loops=1
                    ->  Parallel Bitmap Heap Scan on public.subscription  (cost=322.92..58470.94 rows=11962 width=62) (actual time=8.967..527.330 rows=9149 loops=3)
"                          Output: subscription.id, subscription.source_id, subscription.source_start_date, subscription.source_end_date, subscription.status, subscription.attributes, subscription.created_at, subscription.updated_at, subscription.integration_id, subscription.organization_id, subscription.trial_end_date, subscription.trial_start_date, subscription.last_synced_at, subscription.computed_end_date, subscription.override_end_date, subscription.customer_id, subscription.override_start_date"
                          Recheck Cond: (subscription.integration_id = 162)
                          Heap Blocks: exact=4856
                          Worker 0:  actual time=8.969..556.056 rows=8950 loops=1
                          Worker 1:  actual time=8.954..533.827 rows=9024 loops=1
                          ->  Bitmap Index Scan on subscription_integration_id_e53b1bd5  (cost=0.00..315.75 rows=28709 width=0) (actual time=7.151..7.155 rows=27446 loops=1)
                                Index Cond: (subscription.integration_id = 162)
                                Worker 1:  actual time=7.151..7.155 rows=27446 loops=1
                    ->  Parallel Hash  (cost=47189.88..47189.88 rows=10500 width=41) (actual time=741.375..741.385 rows=8743 loops=3)
"                          Output: customer.id, customer.name"
                          Buckets: 32768  Batches: 1  Memory Usage: 2176kB
                          Worker 0:  actual time=683.803..683.810 rows=7868 loops=1
                          Worker 1:  actual time=683.794..683.808 rows=8225 loops=1
                          ->  Parallel Bitmap Heap Scan on public.customer  (cost=283.74..47189.88 rows=10500 width=41) (actual time=26.742..736.863 rows=8743 loops=3)
"                                Output: customer.id, customer.name"
                                Recheck Cond: (customer.integration_id = 162)
                                Heap Blocks: exact=6420
                                Worker 0:  actual time=17.125..679.507 rows=7868 loops=1
                                Worker 1:  actual time=17.345..679.678 rows=8225 loops=1
                                ->  Bitmap Index Scan on customer_integration_id_afcc30ba  (cost=0.00..277.44 rows=25201 width=0) (actual time=15.062..15.069 rows=26228 loops=1)
                                      Index Cond: (customer.integration_id = 162)
              ->  Index Scan using billing_cycle_subscription_id_b7f65c8b on public.billing_cycle  (cost=0.43..38.70 rows=1 width=16) (actual time=0.131..0.285 rows=3 loops=27446)
"                    Output: billing_cycle.id, billing_cycle.period_start_date, billing_cycle.period_end_date, billing_cycle.created_at, billing_cycle.updated_at, billing_cycle.subscription_id, billing_cycle.invoice_id, billing_cycle.integration_id, billing_cycle.organization_id, billing_cycle.last_synced_at, billing_cycle.is_trial_period"
                    Index Cond: (billing_cycle.subscription_id = subscription.id)
                    Filter: (billing_cycle.integration_id = 162)
                    Worker 0:  actual time=0.135..0.290 rows=3 loops=8950
                    Worker 1:  actual time=0.132..0.288 rows=3 loops=9024
        ->  Index Scan using product_version_billing_cycle_id_c8642f61 on public.product_version  (cost=0.43..8.72 rows=1 width=40) (actual time=0.140..0.146 rows=1 loops=83631)
"              Output: product_version.id, product_version.name, product_version.version_start_date, product_version.version_end_date, product_version.product_mrr, product_version.override_mrr_amount, product_version.quantity, product_version.source_product_id, product_version.source_price_id, product_version.is_metered, product_version.created_at, product_version.updated_at, product_version.billing_cycle_id, product_version.changed_date, product_version.invoice_id, product_version.integration_id, product_version.organization_id, product_version.last_synced_at, product_version.coupon_mrr, product_version.coupon_name, product_version.is_trial_version, product_version.tax_mrr, product_version.tax_name, product_version.total_mrr, product_version.attributes, product_version.query_grouping_id"
              Index Cond: (product_version.billing_cycle_id = billing_cycle.id)
              Filter: (product_version.integration_id = 162)
              Worker 0:  actual time=0.141..0.147 rows=1 loops=27652
              Worker 1:  actual time=0.142..0.149 rows=1 loops=27320
Planning Time: 9.807 ms
JIT:
  Functions: 87
"  Options: Inlining false, Optimization false, Expressions true, Deforming true"
"  Timing: Generation 22.063 ms, Inlining 0.000 ms, Optimization 4.291 ms, Emission 57.598 ms, Total 83.952 ms"
Execution Time: 8151.987 ms

请注意,例如,对于

billing_cycle
,每列都包含在输出中,即使仅使用
id
subscription_id
作为连接键。为什么会这样?这会带来性能问题吗?

我尝试过谷歌搜索并查看了一堆源文档,但找不到这个输出的确切含义。

sql postgresql
1个回答
0
投票

重新形成元组需要大量工作。做得超过必要的程度会减慢速度。因此,每次可以从元组中删除列时,它不会重新形成元组。稍后的节点可以删除额外的列,同时它还可以执行它需要执行的其他重组工作。

© www.soinside.com 2019 - 2024. All rights reserved.