Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qffvE-00Cfx1-7s for pgsql-performance@arkaria.postgresql.org; Mon, 11 Sep 2023 12:21:44 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1qffvC-000Qy9-Jq for pgsql-performance@arkaria.postgresql.org; Mon, 11 Sep 2023 12:21:42 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qffvC-000Qxq-0f for pgsql-performance@lists.postgresql.org; Mon, 11 Sep 2023 12:21:42 +0000 Received: from out-221.mta0.migadu.com ([2001:41d0:1004:224b::dd]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qffv7-003xcn-MQ for pgsql-performance@postgresql.org; Mon, 11 Sep 2023 12:21:40 +0000 Date: Mon, 11 Sep 2023 14:21:30 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=philpep.org; s=key1; t=1694434893; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=YLDZYepzIKP3PSZcu5Zph0V7ysTYNSJGBXs3jj26B9c=; b=RMQO9T58bcySCr8JA+sWQejH69orjkkBtpuvuRgdoiguS8ZAOV7tSHIxOTX3SzwDuXZVaD 2sklv6k+Z34C01jEYb/8NSd7VEgGJOeQLhQ28xrX3GMjNRYdw1XuzBdX2rxJUio7qugzBr 2pz/7+9UuKM0rGuIG2NGQXYbBi9AbcadcN7ue8QN+WAQNDZMrnM8e6QNus2W6jWBcR78Hx pj6s45vX8QX2chT1epBqF09h8yQEqvOD+P3cTfuVrnZF6c4MwUAGSIclhqlw45a3AWHRdR XWUmfkegX1J5RZbv9lZ5FjGspgaa6Cu7BgpfAJO6fAIAT1U//93zcfhOxy0PaQ== X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Philippe Pepiot To: David Rowley Cc: pgsql-performance@postgresql.org Subject: Re: Range partitioning query performance with date_trunc (vs timescaledb) Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Migadu-Flow: FLOW_OUT List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 29/08/2023, David Rowley wrote: > On Tue, 29 Aug 2023 at 19:40, Philippe Pepiot wrote: > > I'm trying to implement some range partitioning on timeseries data. But it > > looks some queries involving date_trunc() doesn't make use of partitioning. > > > > BEGIN; > > CREATE TABLE test ( > > time TIMESTAMP WITHOUT TIME ZONE NOT NULL, > > value FLOAT NOT NULL > > ) PARTITION BY RANGE (time); > > CREATE INDEX test_time_idx ON test(time DESC); > > CREATE TABLE test_y2010 PARTITION OF test FOR VALUES FROM ('2020-01-01') TO ('2021-01-01'); > > CREATE TABLE test_y2011 PARTITION OF test FOR VALUES FROM ('2021-01-01') TO ('2022-01-01'); > > CREATE VIEW vtest AS SELECT DATE_TRUNC('year', time) AS time, SUM(value) AS value FROM test GROUP BY 1; > > EXPLAIN (COSTS OFF) SELECT * FROM vtest WHERE time >= TIMESTAMP '2021-01-01'; > > ROLLBACK; > > > > The plan query all partitions: > > > I wonder if there is a way with a reasonable amount of SQL code to achieve this > > with vanilla postgres ? > > The only options I see for you are > > 1) partition by LIST(date_Trunc('year', time)), or; > 2) use a set-returning function instead of a view and pass the date > range you want to select from the underlying table via parameters. > > I imagine you won't want to do #1. However, it would at least also > allow the aggregation to be performed before the Append if you SET > enable_partitionwise_aggregate=1. > > #2 isn't as flexible as a view as you'd have to create another > function or expand the parameters of the existing one if you want to > add items to the WHERE clause. > > Unfortunately, date_trunc is just a black box to partition pruning, so > it's not able to determine that DATE_TRUNC('year', time) >= > '2021-01-01' is the same as time >= '2021-01-01'. It would be > possible to make PostgreSQL do that, but that's a core code change, > not something that you can do from SQL. Ok I think I'll go for Set-returning function since LIST or RANGE on (date_trunc('year', time)) will break advantage of partitioning when querying with "time betwen x and y". Thanks!