Unix Technical Forum

Fastest way / best practice to calculate "next birthdays"

This is a discussion on Fastest way / best practice to calculate "next birthdays" within the Pgsql Performance forums, part of the PostgreSQL category; --> The subject basically says it all, I'm looking for the fastest (indexable) way to calculate the next birthdays relative ...


Go Back   Unix Technical Forum > Database Server Software > PostgreSQL > Pgsql Performance

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 05-05-2008, 06:53 AM
Hannes Dorbath
 
Posts: n/a
Default Fastest way / best practice to calculate "next birthdays"

The subject basically says it all, I'm looking for the fastest
(indexable) way to calculate the next birthdays relative to NOW() from a
dataset of about 1 million users.

I'm currently using a function based index, but leap year handling /
mapping February 29 to February 28 gives me some headaches.

Is there any best practice to do that in PostgreSQL?


--
Best regards,
Hannes Dorbath
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 05-05-2008, 06:53 AM
Joshua D. Drake
 
Posts: n/a
Default Re: Fastest way / best practice to calculate "next birthdays"

Hannes Dorbath wrote:
> The subject basically says it all, I'm looking for the fastest
> (indexable) way to calculate the next birthdays relative to NOW() from a
> dataset of about 1 million users.
>
> I'm currently using a function based index, but leap year handling /
> mapping February 29 to February 28 gives me some headaches.
>
> Is there any best practice to do that in PostgreSQL?


postgres=# SELECT current_date|| ' a ' || to_char(current_date, 'Day'),

current_date + '1 Year'::interval || ' a ' || to_char(current_date + '1
Year'::interval, 'Day') as next_birthday;
?column? | next_birthday
------------------------+---------------------------------
2008-05-04 a Sunday | 2009-05-04 00:00:00 a Monday

?


Sincerely,

Joshua D. Drake


--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 05-05-2008, 06:53 AM
Hannes Dorbath
 
Posts: n/a
Default Re: Fastest way / best practice to calculate "next birthdays"

Joshua D. Drake wrote:
> postgres=# SELECT current_date|| ' a ' || to_char(current_date, 'Day'),
> current_date + '1 Year'::interval || ' a ' || to_char(current_date + '1
> Year'::interval, 'Day') as next_birthday;
> ?column? | next_birthday
> ------------------------+---------------------------------
> 2008-05-04 a Sunday | 2009-05-04 00:00:00 a Monday
>
> ?


Sorry, I think I phrased the question badly. What I'm after basically is:

http://www.depesz.com/index.php/2007...hday-tomorrow/


--
Best regards,
Hannes Dorbath
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 05-05-2008, 06:53 AM
Zoltan Boszormenyi
 
Posts: n/a
Default Re: Fastest way / best practice to calculate "next birthdays"

Hannes Dorbath írta:
> Joshua D. Drake wrote:
>> postgres=# SELECT current_date|| ' a ' || to_char(current_date, 'Day'),
>> current_date + '1 Year'::interval || ' a ' || to_char(current_date +
>> '1 Year'::interval, 'Day') as next_birthday;
>> ?column? | next_birthday
>> ------------------------+---------------------------------
>> 2008-05-04 a Sunday | 2009-05-04 00:00:00 a Monday
>>
>> ?

>
> Sorry, I think I phrased the question badly. What I'm after basically is:
>
> http://www.depesz.com/index.php/2007...hday-tomorrow/


If you define the same functional index as in the above link:

CREATE OR REPLACE FUNCTION indexable_month_day(date) RETURNS TEXT as $BODY$
SELECT to_char($1, 'MM-DD');
$BODY$ language 'sql' IMMUTABLE STRICT;

create table user_birthdate (
id serial not null primary key,
birthdate date
);
create index user_birthdate_day_idx on user_birthdate (
indexable_month_day(birthdate) );

Then you can use this query:

select count(*) from user_birthdate where indexable_month_day(birthdate)
> '02-28' and indexable_month_day(birthdate) <= '03-01';


In a generic and parametrized way:

select * from user_birthdate
where
indexable_month_day(birthdate) > indexable_month_day(now()::date) and
indexable_month_day(birthdate) <= indexable_month_day((now() + '1
days'::interval)::date);

This will still use the index and it will work for the poor ones
who have birthday every 4 years, too. Assume, it's 02-08 today, 03-01
the next day.
The now() < X <= now() + 1 day range will find 02-29.

--
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5 (permalink)  
Old 05-07-2008, 11:18 AM
Shane Ambler
 
Posts: n/a
Default Re: Fastest way / best practice to calculate "next birthdays"

Hannes Dorbath wrote:

> Sorry, I think I phrased the question badly. What I'm after basically is:
>
> http://www.depesz.com/index.php/2007...hday-tomorrow/
>


OK So what I came up with is - (the times are from a G4 1.25Ghz)

CREATE TABLE birthdaytest
(
id serial PRIMARY KEY,
birthdate date
);


CREATE INDEX idx_bday_month ON birthdaytest
USING btree(extract(month from birthdate));

CREATE INDEX idx_bday_day ON birthdaytest
USING btree(extract(day from birthdate));


insert into birthdaytest (birthdate) values
('1930-01-01'::date+generate_series(0,365*70));

.... I repeated this another 15 times to load some data


vacuum analyse birthdaytest;

\timing

select count(*) from birthdaytest;

> count
> --------
> 408816
> (1 row)
>
> Time: 233.501 ms



select * from birthdaytest
where extract(month from birthdate) = 5
and extract(day from birthdate) between 6 and 12;

> id | birthdate
> --------+------------
> 126 | 1930-05-06
> 127 | 1930-05-07
> 128 | 1930-05-08
> ...
> ...
> 408613 | 1999-05-11
> 408614 | 1999-05-12
> (7840 rows)
>
> Time: 211.237 ms



select * from birthdaytest
where extract(month from birthdate) = extract(month from current_date)
and extract(day from birthdate) between extract(day from current_date)
and extract(day from current_date+14);

> id | birthdate
> --------+------------
> 125 | 1930-05-05
> 126 | 1930-05-06
> 127 | 1930-05-07
> ...
> ...
> 408619 | 1999-05-17
> 408620 | 1999-05-18
> 408621 | 1999-05-19
> (16800 rows)
>
> Time: 483.915 ms



--

Shane Ambler
pgSQL (at) Sheeky (dot) Biz

Get Sheeky @ http://Sheeky.Biz

--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 07:28 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
www.UnixAdminTalk.com