Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1Wg7np-0003Yh-7d for pgsql-performance@arkaria.postgresql.org; Fri, 02 May 2014 07:22:37 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.80) (envelope-from ) id 1Wg7no-0003wU-1L for pgsql-performance@arkaria.postgresql.org; Fri, 02 May 2014 07:22:36 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1Wg7nm-0003wN-PY for pgsql-performance@postgresql.org; Fri, 02 May 2014 07:22:34 +0000 Received: from prod2.officenet.no ([195.159.87.246]) by magus.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1Wg7nh-0000c4-Nl for pgsql-performance@postgresql.org; Fri, 02 May 2014 07:22:32 +0000 Received: from localhost ([127.0.0.1] helo=prod2) by prod2.officenet.no with esmtp (Exim 4.76) (envelope-from ) id 1Wg7lf-0001rG-8F for pgsql-performance@postgresql.org; Fri, 02 May 2014 09:20:23 +0200 Date: Fri, 2 May 2014 09:20:22 +0200 (CEST) From: Andreas Joseph Krogh To: pgsql-performance@postgresql.org Message-ID: In-Reply-To: Subject: Re: Optimize query for listing un-read messages MIME-Version: 1.0 X-Mailer: OfficeNet Mail 1.9.0-SNAPSHOT X-Pg-Spam-Score: -1.9 (-) Content-Type: multipart/related; boundary="----=_Part_106_232651695.1399015222752" List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-performance Precedence: bulk Sender: pgsql-performance-owner@postgresql.org ------=_Part_105_562215785.1399015222752 Content-Type: multipart/related; boundary="----=_Part_106_232651695.1399015222752" ------=_Part_106_232651695.1399015222752 Content-Type: multipart/alternative; boundary="----=_Part_107_988877314.1399015222766" ------=_Part_107_988877314.1399015222766 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable P=C3=A5 fredag 02. mai 2014 kl. 02:17:58, skrev Craig James >: On Thu, May 1, 2014 at 4:26 AM, Andreas Jo= seph=20 Krogh> wrote: I have a schem= a=20 where I have lots of messages and some users who might have read some of th= em.=20 When a message is read by a user I create an entry i a table message_proper= ty=20 holding the property (is_read) for that user.=C2=A0 The schema is as follow= s: [...] =C2=A0 create table person(=C2=A0=C2=A0=C2=A0 id serial primary key, =C2=A0=C2=A0=C2=A0 username varchar not null unique ); =C2=A0 create table message( =C2=A0=C2=A0=C2=A0 id serial primary key, =C2=A0=C2=A0=C2=A0 subject varchar ); =C2=A0 create table message_property( =C2=A0=C2=A0=C2=A0 message_id integer not null references message(id), =C2=A0=C2=A0=C2=A0 person_id integer not null references person(id), =C2=A0=C2=A0=C2=A0 is_read boolean not null default false, =C2=A0=C2=A0=C2=A0 unique(message_id, person_id) ); =C2=A0 [...] =C2=A0So, for person 1 there are 10 unread messages, out o= f a total=20 1mill. 5 of those unread does not have an entry in message_property and 5 h= ave=20 an entry and is_read set to FALSE. =C2=A0 Here's a possible enhancement: ad= d two=20 columns, an indexed timestamp to the message table, and a "timestamp of the= =20 oldest message this user has NOT read" on the person table. If most users r= ead=20 messages in a timely fashion, this would (in most cases) narrow down the=20 portion of the messages table to a tiny fraction of the total -- just those= =20 messages newer than the oldest message this user has not read. =C2=A0 When you sign up a new user, you can set his timestamp to the time = the=20 account was created, since presumably messages before that time don't apply= . =C2=A0 Whether this will help depends a lot on actual use patterns, i.e. d= o users=20 typically read all messages or do they leave a bunch of unread messages sit= ting=20 around forever? =C2=A0 Thanks fort the suggestion. A user must be able to r= ead=20 arbitrary old messages, and messages don't expire. =C2=A0 -- Andreas Jospeh= Krogh=20 CTO / Partner - Visena AS Mobile: +47 909 56 963 andreas@visena.com=20 www.visena.com =20 =C2=A0 ------=_Part_107_988877314.1399015222766 Content-Type: text/html;charset=UTF-8 Content-Transfer-Encoding: quoted-printable
P=C3=A5 fredag 02. mai 2014 kl. 02:17:58, skrev Craig James <cjames@emolecules.com<= /a>>:
On Thu, May 1, 2014 at 4:26 AM, Andreas Joseph Krogh <an= dreas@visena.com> wrote:
I have a schema where I have lots of message= s and some users who might have read some of them. When a message is read b= y a user I create an entry i a table message_property holding the property = (is_read) for that user.
=C2=A0
The schema is as follows:
[...]
=C2=A0
create table person(
=C2=A0=C2=A0=C2=A0 id serial primary key,
=C2=A0=C2=A0=C2=A0 username varchar not null unique
);
=C2=A0
create table message(
=C2=A0=C2=A0=C2=A0 id serial primary key,
=C2=A0=C2=A0=C2=A0 subject varchar
);
=C2=A0
create table message_property(
=C2=A0=C2=A0=C2=A0 message_id integer not null references message(id),
=C2=A0=C2=A0=C2=A0 person_id integer not null references person(id),
=C2=A0=C2=A0=C2=A0 is_read boolean not null default false,
=C2=A0=C2=A0=C2=A0 unique(message_id, person_id)
);
=C2=A0
[...]
=C2=A0So, for person 1 there are 10 unread messages, out of a total 1m= ill. 5 of those unread does not have an entry in message_property and 5 hav= e an entry and is_read set to FALSE.
=C2=A0
Here's a possible enhancement: add two columns, an indexed timestamp t= o the message table, and a "timestamp of the oldest message this user = has NOT read" on the person table. If most users read messages in a ti= mely fashion, this would (in most cases) narrow down the portion of the mes= sages table to a tiny fraction of the total -- just those messages newer th= an the oldest message this user has not read.
=C2=A0
When you sign up a new user, you can set his timestamp to the time the= account was created, since presumably messages before that time don't appl= y.
=C2=A0
Whether this will help depends a lot on actual use patterns, i.e. do u= sers typically read all messages or do they leave a bunch of unread message= s sitting around forever?
=C2=A0
Thanks fort the suggestion. A user must be able to read arbitrary old = messages, and messages don't expire.
=C2=A0
--
Andrea= s Jospeh Krogh
CTO / Partner<= /span> - Visena AS
Mobile: +47 90= 9 56 963
3D""
=C2=A0
------=_Part_107_988877314.1399015222766-- ------=_Part_106_232651695.1399015222752 Content-Type: image/png Content-Transfer-Encoding: base64 Content-Disposition: inline Content-ID: iVBORw0KGgoAAAANSUhEUgAAAIUAAAAYCAYAAADUIj6hAAAABHNCSVQICAgIfAhkiAAABzBJREFU aEPtmNFxHDcMhmVP3i1VECpvnjzkVIHWFfhcgVcVRKrAUgWRK/C6Al8H3lTgy0PGbzFdQc4VJP/H ADs43q6kROeJNbOYgQACIAgCWJKng4MZ5gxUGXh0U0b+SIuF9G+EWXj2Q15vbrE/NPtk9uub7Gfd t5mBx1NhqSEo8HshjbEUtlO2yIM9tsx5dZP9rPt2MzDZFAqZE4LGcFjdsg3saQaHt7fY70X949On aS+OZidDBkavD33157L4xaw2os+Mp/DAC10l2XhOCeStj0W5ajrJL8WfCi80Xgf9vVlrhg9yRONe /f7xI2vNsIcM7JwU9o6oGyJrLT8JOA1aX9sKP4wl94bAniukEbo/n7YPmuTETzIab4Y9ZWCrKexd 8M58lxPCvvD6aihfvexbEQoPYO8NQRO0JnddGO6FJYaVsBde7cXj7KRk4LsqDxQzCYeGsJNgaXZe +JXkyGgWINq3Gp+bHNILz+wEYs5qH1eJrouNrpDXtk4O6x1IvtD40GWyJYYdkF0jIbYZlN16xygI gl9smbMDsmFdfAKb23xGB8H/mv3tOJfArs1kukk79DEPdQ5u0g1vCvvqKXIW8mZYW+F3Tg4r8HvZ kQCCLydK8EFMQCe5N8RgL9mRG0SqQFuNvdE6beSs0qPDBuCdg0+gvClso8SbTO4ki7mQzQqBrcMH QPwReg2wW8umEe/+L8T/LEzBGF9nXjzZ46s+ITHvhegW8LL39xm6App7KYL/GE+vcYnFbJiP/0aY hdiCnRC7jaj7eiK2ETInC5PRF6LYkSN0+HabF75WuT6syCyI0YkVGGMvUC33AmfZTDUEj8u6IVhu EhRUJ2U2g6UlugyNb03Hl9obHwlxJbcRzcYjO4QPjVfGFTQav4vrmp7cpMp2qbHnBxWJbisbho2Q XI6C1sIHDUFhH4Hij4UbIev66eANeiwbkA+LBsO36zAHzoXU7AhbqLAXEiOYTXcSdO8VS9L4wN8U BIYhBd6oSUgYMijOkecRuTdQa/YiBXhbXFcnCnI2SrfeBG9NydrLYMhGHa5qB9pQIxlzAE6Okjzx JO5afGe6kmhBicWKQNKuTZ5EW+MjQY8v/9rQ0bhJSJyNGUe/JH1t8h1iMbdSPAvxHYin6YmN9YBX QmTYZZNh14vHhhhal5vtcIrJjmvszPRJdExH3MWHvykoBEc9CoCGWJisOLOGoCORs1FvIMbYA8z3 kwM59oemy6LlWrLxFLmWgiQAfEGd8S+NssbK+EhyGLxUkhhiy717waBqHOJYSEacwBejkFNhjJNj v/gANOdQxPfciP/JVBCK2cOIcg3RRJ+CPrLPNVhhN6F38VKMF3XLlIJrjU5C8gMFxvKDvOcPc4rV NjCn7KM0BV+161V8viSCuJZ8SITGJGEh7IUUlxOFMYUH1kJOCN4Wh+I5pqCuK01k40kSNtnKiKIl UfxAgW5sU5JlS05rtt5YFJF1SWoqHv6BRgQcA4/bdb9WRjmMk3jyUMAbIoyJq9e4cVmgzKt9j5gN J/aYDhk+hhjExwaPcz5PObA5Zd9bvz5UzCTZuZDidu5AchpiKSwPR+TV1bCWqBQ9nCjJ5neivC82 Nr4LeS2j1gw5LUqwBuhGQQU5UwHeSslXkwIynz2U2A2yKDgG7OffwLA3TpGRpk0Tzpj3ZEJXi/GR a6GN0e0NtppChePdcAz1FTS+FN8Kpxoiykk+J8fC5tenjbu9kSqpHLu9jBrhUuhNwVGbpyZrzrl0 HPVD8SXj5EOOD/eDC64VjvYBZLuUbIVAfBN1t/C/SU+cAGtdGo+fVnzycUX5wmn6eCKPmWYJG2E/ ppTsuRCbvUD9fwquksG5GqLVKhzDQ3GrEyLKSXhsiK3T5j9EyxffCFOYi2wUlPyFFDQAhehESDjQ GoX0ho0oj8RPou6TxHJdcT0NTcWkO0AnG7+uXsnHqcas/72wvWF+mSf7N/Watp9kTXoluzeS0fB9 9CcZ/hvhSZTfh99pispZOXL9KrGrARkNUMu9ITbScZWs7xOYNt9pwxSZtYDsX/GE3xTkrXgwAsXm fud08FiTeC+m2/o7ppo+PTS/NBK5ARpDG5YHr++DpmVfreYdiX8mnp+DzPEG9WbqJON0JBenZofs sxBA1gj5NXGvfJu/Qh7HwQh/VDUEyUxCit5hH94QfKkEdu+GwK8BX0hvCF+D67xhjmXQCXMwJCZ+ olK0A1EKRCE4snsh42w8Mv/Zhxw9iD7Cjo7CyQC/KyF6oBfShL4PYgG+CHsYKyZxvxZSZBAgjhIz YDz+AbfD37GtbaoSKzgGt+lKfI/GZtay6vG4VXTpPsh+IcQhOk9I7WYeP5AM3HZ9+DaSGIp9HIuu huC4pCGGx+YD2fcc5tfIAA0h/Et4/jX8zz4fWAasIf4UbR9Y6HO4d8jAnd4U0Y8ageuCB+c+H5R3 CHU2mTMwZ+B/y8DfSMBLLOYXVuEAAAAASUVORK5CYII= ------=_Part_106_232651695.1399015222752-- ------=_Part_105_562215785.1399015222752--