add batch remove batch split batch comment selection show hidden batches hide batch highlight batch
db<>fiddle
donate feedback about
By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
Help with an interesting Postgres question: Why isn't an Index Only Scan used on a partition accessed via the parent table?.
create table customer(
id,name,integration_id
) as values
(1,'segmented_customer_name1',162);

create table subscription(
id,customer_id,integration_id,override_start_date,source_start_date,override_end_date,computed_end_date
) as values
(1,1,162,'override_start_date','source_start_date','override_end_date','computed_end_date');

create table product_version(
id,billing_cycle_id,integration_id,
override_mrr_amount,total_mrr,version_start_date,version_end_date
) as values
(1,1,162,'override_mrr_amount','total_mrr','version_start_date','version_end_date');

create table billing_cycle(
id int,subscription_id int,integration_id int,something_toasted text,organization_id int
);
alter table billing_cycle alter column something_toasted set storage external;
insert into billing_cycle values
(1,1,162,(select string_agg(a,',')
from generate_series(1,1e5)g
,lateral(select g,gen_random_uuid()::text a)_),999 ),
(2,2,163,(select string_agg(a,',')
from generate_series(1,1e5)g
,lateral(select g,gen_random_uuid()::text a)_),999 );
SELECT 1
SELECT 1
SELECT 1
CREATE TABLE
ALTER TABLE
INSERT 0 2
vacuum analyze billing_cycle;
VACUUM
select pg_column_compression(something_toasted),
pg_size_pretty(
pg_column_size(something_toasted)::bigint)
from billing_cycle;

select t1.oid, t1.relname, t1.relkind, t1.relpages, t1.reltuples,
t1.reltoastrelid, t2.relkind, t2.relpages, t2.reltuples
from pg_class t1
inner join pg_class t2
on t1.reltoastrelid = t2.oid
where t1.relkind = 'r'
and t2.relkind = 't'
and t1.relname='billing_cycle';

select oid::regclass from pg_class where reltoastrelid='billing_cycle'::regclass;
pg_column_compression pg_size_pretty
null 3613 kB
null 3613 kB
SELECT 2
oid relname relkind relpages reltuples reltoastrelid relkind relpages reltuples
16399 billing_cycle r 1 2 16402 t 927 3708
SELECT 1
oid
SELECT 0
prepare your_query as
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;

EXPLAIN (ANALYZE, VERBOSE) execute your_query;
execute your_query;
PREPARE
QUERY PLAN
Nested Loop (cost=0.00..58.14 rows=1 width=292) (actual time=0.020..0.023 rows=1 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
  Join Filter: ((customer.id = subscription.customer_id) AND (subscription.id = billing_cycle.subscription_id))
  -> Nested Loop (cost=0.00..42.11 rows=1 width=168) (actual time=0.016..0.018 rows=1 loops=1)
        Output: customer.id, customer.name, billing_cycle.subscription_id, product_version.override_mrr_amount, product_version.total_mrr, product_version.version_start_date, product_version.version_end_date
        -> Nested Loop (cost=0.00..17.05 rows=1 width=132) (actual time=0.013..0.014 rows=1 loops=1)
              Output: billing_cycle.subscription_id, product_version.override_mrr_amount, product_version.total_mrr, product_version.version_start_date, product_version.version_end_date
              Join Filter: (billing_cycle.id = product_version.billing_cycle_id)
              -> Seq Scan on public.billing_cycle (cost=0.00..1.02 rows=1 width=8) (actual time=0.007..0.007 rows=1 loops=1)
                    Output: billing_cycle.id, billing_cycle.subscription_id, billing_cycle.integration_id, billing_cycle.something_toasted, billing_cycle.organization_id
                    Filter: (billing_cycle.integration_id = 162)
                    Rows Removed by Filter: 1
              -> Seq Scan on public.product_version (cost=0.00..16.00 rows=2 width=132) (actual time=0.004..0.004 rows=1 loops=1)
                    Output: product_version.id, product_version.billing_cycle_id, product_version.integration_id, product_version.override_mrr_amount, product_version.total_mrr, product_version.version_start_date, product_version.version_end_date
                    Filter: (product_version.integration_id = 162)
        -> Seq Scan on public.customer (cost=0.00..25.00 rows=6 width=36) (actual time=0.002..0.003 rows=1 loops=1)
              Output: customer.id, customer.name, customer.integration_id
              Filter: (customer.integration_id = 162)
  -> Seq Scan on public.subscription (cost=0.00..16.00 rows=2 width=136) (actual time=0.003..0.003 rows=1 loops=1)
        Output: subscription.id, subscription.customer_id, subscription.integration_id, subscription.override_start_date, subscription.source_start_date, subscription.override_end_date, subscription.computed_end_date
        Filter: (subscription.integration_id = 162)
Planning Time: 0.540 ms
Execution Time: 0.047 ms
EXPLAIN
customer_id customer_name sub_override_start_ts sub_source_start_ts sub_override_end_ts sub_computed_end_ts override_mrr_amount total_mrr version_start_ts version_end_ts
1 segmented_customer_name1 override_start_date source_start_date override_end_date computed_end_date override_mrr_amount total_mrr version_start_date version_end_date
SELECT 1
prepare your_query_without_cte as
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 customer segmented_customer
JOIN subscription segmented_subscription
ON segmented_customer.id = segmented_subscription.customer_id
AND segmented_subscription.integration_id = 162
AND segmented_customer.integration_id = 162
JOIN billing_cycle segmented_billing_cycle
ON segmented_subscription.id = segmented_billing_cycle.subscription_id
AND segmented_billing_cycle.integration_id = 162
JOIN product_version segmented_product_version
ON segmented_billing_cycle.id = segmented_product_version.billing_cycle_id
AND segmented_product_version.integration_id = 162;

EXPLAIN (ANALYZE, VERBOSE) execute your_query_without_cte;
execute your_query_without_cte;
PREPARE
QUERY PLAN
Nested Loop (cost=0.00..58.14 rows=1 width=292) (actual time=0.016..0.018 rows=1 loops=1)
  Output: segmented_customer.id, segmented_customer.name, segmented_subscription.override_start_date, segmented_subscription.source_start_date, segmented_subscription.override_end_date, segmented_subscription.computed_end_date, segmented_product_version.override_mrr_amount, segmented_product_version.total_mrr, segmented_product_version.version_start_date, segmented_product_version.version_end_date
  Join Filter: ((segmented_customer.id = segmented_subscription.customer_id) AND (segmented_subscription.id = segmented_billing_cycle.subscription_id))
  -> Nested Loop (cost=0.00..42.11 rows=1 width=168) (actual time=0.012..0.014 rows=1 loops=1)
        Output: segmented_customer.id, segmented_customer.name, segmented_billing_cycle.subscription_id, segmented_product_version.override_mrr_amount, segmented_product_version.total_mrr, segmented_product_version.version_start_date, segmented_product_version.version_end_date
        -> Nested Loop (cost=0.00..17.05 rows=1 width=132) (actual time=0.010..0.011 rows=1 loops=1)
              Output: segmented_billing_cycle.subscription_id, segmented_product_version.override_mrr_amount, segmented_product_version.total_mrr, segmented_product_version.version_start_date, segmented_product_version.version_end_date
              Join Filter: (segmented_billing_cycle.id = segmented_product_version.billing_cycle_id)
              -> Seq Scan on public.billing_cycle segmented_billing_cycle (cost=0.00..1.02 rows=1 width=8) (actual time=0.006..0.007 rows=1 loops=1)
                    Output: segmented_billing_cycle.id, segmented_billing_cycle.subscription_id, segmented_billing_cycle.integration_id, segmented_billing_cycle.something_toasted, segmented_billing_cycle.organization_id
                    Filter: (segmented_billing_cycle.integration_id = 162)
                    Rows Removed by Filter: 1
              -> Seq Scan on public.product_version segmented_product_version (cost=0.00..16.00 rows=2 width=132) (actual time=0.002..0.002 rows=1 loops=1)
                    Output: segmented_product_version.id, segmented_product_version.billing_cycle_id, segmented_product_version.integration_id, segmented_product_version.override_mrr_amount, segmented_product_version.total_mrr, segmented_product_version.version_start_date, segmented_product_version.version_end_date
                    Filter: (segmented_product_version.integration_id = 162)
        -> Seq Scan on public.customer segmented_customer (cost=0.00..25.00 rows=6 width=36) (actual time=0.002..0.002 rows=1 loops=1)
              Output: segmented_customer.id, segmented_customer.name, segmented_customer.integration_id
              Filter: (segmented_customer.integration_id = 162)
  -> Seq Scan on public.subscription segmented_subscription (cost=0.00..16.00 rows=2 width=136) (actual time=0.002..0.002 rows=1 loops=1)
        Output: segmented_subscription.id, segmented_subscription.customer_id, segmented_subscription.integration_id, segmented_subscription.override_start_date, segmented_subscription.source_start_date, segmented_subscription.override_end_date, segmented_subscription.computed_end_date
        Filter: (segmented_subscription.integration_id = 162)
Planning Time: 0.230 ms
Execution Time: 0.039 ms
EXPLAIN
customer_id customer_name sub_override_start_ts sub_source_start_ts sub_override_end_ts sub_computed_end_ts override_mrr_amount total_mrr version_start_ts version_end_ts
1 segmented_customer_name1 override_start_date source_start_date override_end_date computed_end_date override_mrr_amount total_mrr version_start_date version_end_date
SELECT 1
insert into billing_cycle
select random()*100,
random()*100,
random()*100,
random(),
random()*1000
from generate_series(1,2e4);
INSERT 0 20000
create index on billing_cycle(id,subscription_id,integration_id);
CREATE INDEX
vacuum analyze billing_cycle;
VACUUM
deallocate your_query_without_cte;
prepare your_query_without_cte as
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 customer segmented_customer
JOIN subscription segmented_subscription
ON segmented_customer.id = segmented_subscription.customer_id
AND segmented_subscription.integration_id = 162
AND segmented_customer.integration_id = 162
JOIN billing_cycle segmented_billing_cycle
ON segmented_subscription.id = segmented_billing_cycle.subscription_id
AND segmented_billing_cycle.integration_id = 162
JOIN product_version segmented_product_version
ON segmented_billing_cycle.id = segmented_product_version.billing_cycle_id
AND segmented_product_version.integration_id = 162;

EXPLAIN (ANALYZE, VERBOSE) execute your_query_without_cte;
execute your_query_without_cte;
DEALLOCATE
PREPARE
QUERY PLAN
Nested Loop (cost=0.29..65.84 rows=1 width=292) (actual time=0.034..0.037 rows=1 loops=1)
  Output: segmented_customer.id, segmented_customer.name, segmented_subscription.override_start_date, segmented_subscription.source_start_date, segmented_subscription.override_end_date, segmented_subscription.computed_end_date, segmented_product_version.override_mrr_amount, segmented_product_version.total_mrr, segmented_product_version.version_start_date, segmented_product_version.version_end_date
  -> Nested Loop (cost=0.00..41.19 rows=1 width=168) (actual time=0.018..0.019 rows=1 loops=1)
        Output: segmented_customer.id, segmented_customer.name, segmented_subscription.override_start_date, segmented_subscription.source_start_date, segmented_subscription.override_end_date, segmented_subscription.computed_end_date, segmented_subscription.id
        Join Filter: (segmented_customer.id = segmented_subscription.customer_id)
        -> Seq Scan on public.customer segmented_customer (cost=0.00..25.00 rows=6 width=36) (actual time=0.009..0.010 rows=1 loops=1)
              Output: segmented_customer.id, segmented_customer.name, segmented_customer.integration_id
              Filter: (segmented_customer.integration_id = 162)
        -> Materialize (cost=0.00..16.01 rows=2 width=136) (actual time=0.006..0.007 rows=1 loops=1)
              Output: segmented_subscription.override_start_date, segmented_subscription.source_start_date, segmented_subscription.override_end_date, segmented_subscription.computed_end_date, segmented_subscription.customer_id, segmented_subscription.id
              -> Seq Scan on public.subscription segmented_subscription (cost=0.00..16.00 rows=2 width=136) (actual time=0.003..0.004 rows=1 loops=1)
                    Output: segmented_subscription.override_start_date, segmented_subscription.source_start_date, segmented_subscription.override_end_date, segmented_subscription.computed_end_date, segmented_subscription.customer_id, segmented_subscription.id
                    Filter: (segmented_subscription.integration_id = 162)
  -> Nested Loop (cost=0.29..24.64 rows=1 width=132) (actual time=0.013..0.015 rows=1 loops=1)
        Output: segmented_billing_cycle.subscription_id, segmented_product_version.override_mrr_amount, segmented_product_version.total_mrr, segmented_product_version.version_start_date, segmented_product_version.version_end_date
        -> Seq Scan on public.product_version segmented_product_version (cost=0.00..16.00 rows=2 width=132) (actual time=0.002..0.003 rows=1 loops=1)
              Output: segmented_product_version.id, segmented_product_version.billing_cycle_id, segmented_product_version.integration_id, segmented_product_version.override_mrr_amount, segmented_product_version.total_mrr, segmented_product_version.version_start_date, segmented_product_version.version_end_date
              Filter: (segmented_product_version.integration_id = 162)
        -> Index Only Scan using billing_cycle_id_subscription_id_integration_id_idx on public.billing_cycle segmented_billing_cycle (cost=0.29..4.31 rows=1 width=8) (actual time=0.009..0.010 rows=1 loops=1)
              Output: segmented_billing_cycle.id, segmented_billing_cycle.subscription_id, segmented_billing_cycle.integration_id
              Index Cond: ((segmented_billing_cycle.id = segmented_product_version.billing_cycle_id) AND (segmented_billing_cycle.subscription_id = segmented_subscription.id) AND (segmented_billing_cycle.integration_id = 162))
              Heap Fetches: 0
Planning Time: 0.589 ms
Execution Time: 0.083 ms
EXPLAIN
customer_id customer_name sub_override_start_ts sub_source_start_ts sub_override_end_ts sub_computed_end_ts override_mrr_amount total_mrr version_start_ts version_end_ts
1 segmented_customer_name1 override_start_date source_start_date override_end_date computed_end_date override_mrr_amount total_mrr version_start_date version_end_date
SELECT 1