Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1YjGGG-0008C3-5d for pgsql-sql@arkaria.postgresql.org; Sat, 18 Apr 2015 00:05:28 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.80) (envelope-from ) id 1YjGGF-00073Y-FZ for pgsql-sql@arkaria.postgresql.org; Sat, 18 Apr 2015 00:05:27 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1YjGGD-00073O-T8 for pgsql-sql@postgresql.org; Sat, 18 Apr 2015 00:05:26 +0000 Received: from mail-pd0-x22a.google.com ([2607:f8b0:400e:c02::22a]) by makus.postgresql.org with esmtps (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.80) (envelope-from ) id 1YjGG9-0000Fl-MB for pgsql-sql@postgresql.org; Sat, 18 Apr 2015 00:05:23 +0000 Received: by pdbnk13 with SMTP id nk13so143142478pdb.0 for ; Fri, 17 Apr 2015 17:05:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=WArL/3D2utIz87aIQWZcBDcuDGlWMMOtHg5rGNlfq9w=; b=QYfyzBQKmRzSZXVt2ESLOCV7FvCoCPoDtmQxNq9rdlGtLI2iWDtgiggP0d7C8LUBXQ 8VN/42KxwPBNketJfWw3ZDay+iFcMLRw6wHpyB77HGuVYXU2WLpROxCBw7wI9rtQk7fo lpLvterkP6aVzXaUkkP6p3UQnQgZGdhxFLVKzP8s5TEuRgOWfS2A/+vYX0/CxlDKk/fe M3omDTlVx9BlrUvr9jFjH6EB7du/Trq+qd1sh3YJR/PkERWUdB6Tnoi0s1I6druFch3Z rvm6QgAN9Yn91oEim+Sw6dLuDtyIqQmasyAVF9BFj9jnByvdsCvgybb4XbOne1A/RsGd 61Pw== X-Received: by 10.68.216.99 with SMTP id op3mr575855pbc.69.1429315520357; Fri, 17 Apr 2015 17:05:20 -0700 (PDT) MIME-Version: 1.0 Received: by 10.70.17.164 with HTTP; Fri, 17 Apr 2015 17:05:00 -0700 (PDT) In-Reply-To: References: From: Naresh Kumar Date: Fri, 17 Apr 2015 19:05:00 -0500 Message-ID: Subject: Re: Best way to aggregate sum for each month To: Andreas Joseph Krogh Cc: pgsql-sql Content-Type: multipart/related; boundary=e89a8ff25364ded3560513f47326 X-Pg-Spam-Score: -2.4 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-sql Precedence: bulk Sender: pgsql-sql-owner@postgresql.org --e89a8ff25364ded3560513f47326 Content-Type: multipart/alternative; boundary=e89a8ff25364ded3520513f47325 --e89a8ff25364ded3520513f47325 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable I wrote it in the form of cte for readability purpose. If you are aggregating by month date and sure that there will be atleast one record for every month you don't require to generate the series and JOIN. On Fri, Apr 17, 2015 at 6:46 PM, Andreas Joseph Krogh wrote: > From what I can see your query performs worse, as CTEs are > optimisation-fences. Your query needs to scans thru all activity_log > entries, then do Merge Left Join . > Maybe there's no way to optimize the Merge Left Join node which takes > ~300ms? > > -- > *Andreas Joseph Krogh* > CTO / Partner - Visena AS > Mobile: +47 909 56 963 > andreas@visena.com > =E2=80=8B=E2=80=8B > www.visena.com > > > > P=C3=A5 l=C3=B8rdag 18. april 2015 kl. 01:29:37, skrev Naresh Kumar < > narain337@gmail.com>: > > Try this, > > > ;WITH cte as > ( > SELECT date_trunc('month', log.start_date::timestamp without time zone) A= S > log_date, sum(log.duration) / (3600 * 1000)::NUMERIC as total_duration > FROM activity_log > GROUP BY date_trunc('month', log.start_date::timestamp without time zone) > ) > > SELECT q.start_date, cte.total_duration > FROM > (SELECT cast(generate_series('2014-01-01' :: DATE, '2014-12-01' :: > DATE, '1 month') AS DATE) as start_date) AS q > LEFT OUTER JOIN cte ON cte.log_date =3D q.start_date > > On Fri, Apr 17, 2015 at 5:10 PM, Andreas Joseph Krogh > wrote: >> >> Hi all. >> >> I'm using PG-9.4. >> >> I'm having a table, activity_log, which holds activities with duration >> for a given date. >> I'm trying to sum the duration for each month in a given year and am >> currently doing it like this: >> >> >> select q.start_date >> , sum(log.duration) / (3600 * 1000)::NUMERIC as total_durationFROM = (SELECT cast(generate_series('2014-01-01' :: DATE, '2014-12-01' :: DATE, = '1 month') AS DATE) as start_date) AS q >> LEFT OUTER JOIN activity_log log ON date_trunc('month', log.start_da= te::timestamp without time zone) =3D q.start_dateGROUP BY q.start_dateORDER= BY q.start_date >> ; >> >> I have the current index defined: >> >> >> create index activity_start_month ON activity_log(date_trunc('month', st= art_date::timestamp without time zone)); >> >> >> >> Here's the explain plan: >> >> >> QUERY PLAN >> >> ------------------------------------------------------------------------= ---------------------------------------------------------------------------= ---------------------------------------------------------------------------= ----------------- >> GroupAggregate (cost=3D65.27..91102.17 rows=3D200 width=3D12) (actual >> time=3D179.983..344.517 rows=3D12 loops=3D1) >> Group Key: ((generate_series(('2014-01-01'::date)::timestamp with tim= e >> zone, ('2014-12-01'::date)::timestamp with time zone, '1 >> mon'::interval))::date) >> -> Merge Left Join (cost=3D65.27..82950.79 rows=3D1629675 width=3D1= 2) >> (actual time=3D163.894..310.011 rows=3D143551 loops=3D1) >> Merge Cond: (((generate_series(('2014-01-01'::date)::timestamp >> with time zone, ('2014-12-01'::date)::timestamp with time zone, '1 >> mon'::interval))::date) =3D date_trunc('month'::text, >> (log.start_date)::timestamp without time zone)) >> -> Sort (cost=3D64.84..67.34 rows=3D1000 width=3D4) (actual >> time=3D0.045..0.052 rows=3D12 loops=3D1) >> Sort Key: >> ((generate_series(('2014-01-01'::date)::timestamp with time zone, >> ('2014-12-01'::date)::timestamp with time zone, '1 mon'::interval))::dat= e) >> Sort Method: quicksort Memory: 25kB >> -> Result (cost=3D0.00..5.01 rows=3D1000 width=3D0) (ac= tual >> time=3D0.017..0.031 rows=3D12 loops=3D1) >> -> Materialize (cost=3D0.42..51097.29 rows=3D325935 width=3D1= 2) >> (actual time=3D0.032..227.692 rows=3D323180 loops=3D1) >> -> Index Scan using activity_start_month on activity_log >> log (cost=3D0.42..50282.45 rows=3D325935 width=3D12) (actual time=3D0.0= 29..185.746 >> rows=3D323180 loops=3D1) >> Planning time: 0.201 ms >> Execution time: 344.645 ms >> (12 rows) >> >> >> Are there any ways to improve this? >> >> Thanks. >> >> -- >> *Andreas Joseph Krogh* >> CTO / Partner - Visena AS >> Mobile: +47 909 56 963 >> andreas@visena.com >> www.visena.com >> >> > > > > -- > *Andreas Joseph Krogh* > CTO / Partner - Visena AS > Mobile: +47 909 56 963 > andreas@visena.com > www.visena.com > > > --e89a8ff25364ded3520513f47325 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
I wrote it in the form of cte for readability= purpose.=C2=A0

If you are aggregating by month date and sure that there will= be atleast one record for every month you don't require to generate th= e series and JOIN.=C2=A0

=

On Fri, Apr 17, 2= 015 at 6:46 PM, Andreas Joseph Krogh <andreas@visena.com> w= rote:
From what I can see your query performs worse, as CTEs are optimisatio= n-fences. Your query needs to scans thru all activity_log entries, then do = Merge Left Join .
Maybe there's no way to optimize the Merge Left Join node which ta= kes ~300ms?
=C2=A0
--
Andreas= Joseph Krogh
CTO / Partner - Visena AS
3D""
=C2=A0
=C2=A0
P=C3=A5 l=C3=B8rdag 18. april 2015 kl. 01:29:37, skrev Naresh Kumar &l= t;narain337@gmail.= com>:
Try this,
=C2=A0
=C2=A0
;WITH cte as
(
SELECT date_trunc('month', log.start_d= ate::timestamp without time zone) AS log_date, sum(log.duration) / (3600 * = 1000)::NUMERIC as total_duration
FROM activity_log
GROUP BY date_trunc('month', log.start= _date::timestamp without time zone)
)
=C2=A0
SELECT q.start_date, cte.total_duration=
FROM
=C2=A0 =C2=A0 (SELECT cast(generate_series(= 9;2014-01-01' :: DATE, '2014-12-01' :: DATE, '1 month')= AS DATE) as start_date) AS q
=C2=A0 =C2=A0 LEFT OUTER JOIN cte ON cte.log_d= ate =3D q.start_date
=C2=A0
On Fri, Apr 17, 2015 at 5:10 PM, Andreas Joseph = Krogh <andreas@visena.com> wrote:
Hi all.
=C2=A0
I'm using PG-9.4.
=C2=A0
I'm having a table, activity_log, which holds activities with dura= tion for a given date.
I'm trying to sum the duration for each month in a given year and = am currently doing it like this:
=C2=A0
select
    q.start_date
    , sum(log.duration) / (3=
600 * 1000)::NUMERIC as total_duration
FROM
    (SELECT cast(generate_series('2014-01-01' :: DATE, '2014-12-01' :: DATE, '1 month') AS DATE) as start_date) AS q
    LEFT OUTER JOIN activity_log log ON=
 date_trunc('month', log.start_date::timestamp without time zone) =3D q.start_da=
te
GROUP BY q.start=
_date
ORDER BY q.start=
_date
;

I have the current index defined:
=C2=A0
create index activity_star=
t_month ON activ=
ity_log(date_trunc('month', start_date::timestamp without time zo=
ne));

=C2=A0
Here's the explain plan:
=C2=A0
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 QUERY PLAN
---------------------------------------------------------------------------= ---------------------------------------------------------------------------= ---------------------------------------------------------------------------= --------------
=C2=A0GroupAggregate=C2=A0 (cost=3D65.27..91102.17 rows=3D200 width=3D12) (= actual time=3D179.983..344.517 rows=3D12 loops=3D1)
=C2=A0=C2=A0 Group Key: ((generate_series(('2014-01-01'::date)::tim= estamp with time zone, ('2014-12-01'::date)::timestamp with time zo= ne, '1 mon'::interval))::date)
=C2=A0=C2=A0 ->=C2=A0 Merge Left Join=C2=A0 (cost=3D65.27..82950.79 rows= =3D1629675 width=3D12) (actual time=3D163.894..310.011 rows=3D143551 loops= =3D1)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Merge Cond: (((generate_se= ries(('2014-01-01'::date)::timestamp with time zone, ('2014-12-= 01'::date)::timestamp with time zone, '1 mon'::interval))::date= ) =3D date_trunc('month'::text, (log.start_date)::timestamp without= time zone))
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ->=C2=A0 Sort=C2=A0 (co= st=3D64.84..67.34 rows=3D1000 width=3D4) (actual time=3D0.045..0.052 rows= =3D12 loops=3D1)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 Sort Key: ((generate_series(('2014-01-01'::date)::timesta= mp with time zone, ('2014-12-01'::date)::timestamp with time zone, = '1 mon'::interval))::date)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 Sort Method: quicksort=C2=A0 Memory: 25kB
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 ->=C2=A0 Result=C2=A0 (cost=3D0.00..5.01 rows=3D1000 width=3D0= ) (actual time=3D0.017..0.031 rows=3D12 loops=3D1)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ->=C2=A0 Materialize=C2= =A0 (cost=3D0.42..51097.29 rows=3D325935 width=3D12) (actual time=3D0.032..= 227.692 rows=3D323180 loops=3D1)
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 ->=C2=A0 Index Scan using activity_start_month on activity_log= log=C2=A0 (cost=3D0.42..50282.45 rows=3D325935 width=3D12) (actual time=3D= 0.029..185.746 rows=3D323180 loops=3D1)
=C2=A0Planning time: 0.201 ms
=C2=A0Execution time: 344.645 ms
(12 rows)
=C2=A0
=C2=A0
Are there any ways to improve this?
=C2=A0
Thanks.
=C2=A0
--
Andreas= Joseph Krogh
CTO / Partner - Visena AS
3D""
=C2=A0
=C2=A0
=C2=A0
--
Andreas= Joseph Krogh
CTO / Partner - Visena AS
3D""
=C2=A0

--e89a8ff25364ded3520513f47325-- --e89a8ff25364ded3560513f47326 Content-Type: image/png Content-Disposition: inline Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: ff5d5c2bd27b4260_0.3 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 --e89a8ff25364ded3560513f47326 Content-Type: image/png Content-Disposition: inline Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: ff5d5c2bd27b4260_0.2 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 --e89a8ff25364ded3560513f47326 Content-Type: image/png Content-Disposition: inline Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: ff5d5c2bd27b4260_0.1 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 --e89a8ff25364ded3560513f47326--