Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1WfvpB-00015a-FB for pgsql-performance@arkaria.postgresql.org; Thu, 01 May 2014 18:35:13 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.80) (envelope-from ) id 1WfvpA-0001TW-VQ for pgsql-performance@arkaria.postgresql.org; Thu, 01 May 2014 18:35:13 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1WfvpA-0001TN-3W for pgsql-performance@postgresql.org; Thu, 01 May 2014 18:35:12 +0000 Received: from huygens.functor.nl ([2a01:7e00::f03c:91ff:fe70:abdd]) by magus.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1Wfvp7-0003oE-3W for pgsql-performance@postgresql.org; Thu, 01 May 2014 18:35:11 +0000 Received: from [192.168.1.12] (unknown [92.109.180.197]) by huygens.functor.nl (Postfix) with ESMTPSA id 3DFB9CECF for ; Thu, 1 May 2014 20:35:08 +0200 (CEST) Message-ID: <536293DB.4010505@functor.nl> Date: Thu, 01 May 2014 20:35:07 +0200 From: Jochem Berndsen User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Icedove/24.4.0 MIME-Version: 1.0 To: pgsql-performance@postgresql.org Subject: Re: Optimize query for listing un-read messages References: In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Pg-Spam-Score: -2.6 (--) 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 Hi Andreas, [New to this list, forgive my ignorance.] On 05/01/2014 01:26 PM, Andreas Joseph Krogh wrote: > I'm using PostgreSQL 9.3.2 on x86_64-unknown-linux-gnu My machine has PostgreSQL 9.1.13 on x86_64-unknown-linux-gnu. > I have a schema where I have lots of messages and some users who might > have read some of them. When a message is read by a user I create an > entry i a table message_property holding the property (is_read) for > that user. > The schema is as follows: > drop table if exists message_property; > drop table if exists message; > drop table if exists person; > create table person( > id serial primary key, > username varchar not null unique > ); > create table message( > id serial primary key, > subject varchar > ); > create table message_property( > message_id integer not null references message(id), > person_id integer not null references person(id), > is_read boolean not null default false, > unique(message_id, person_id) > ); [snip] > So, for person 1 there are 10 unread messages, out of a total 1mill. 5 > of those unread does not have an entry in message_property and 5 have > an entry and is_read set to FALSE. > I have the following query to list all un-read messages for person > with id=1: > SELECT > m.id AS message_id, > prop.person_id, > coalesce(prop.is_read, FALSE) AS is_read, > m.subject > FROM message m > LEFT OUTER JOIN message_property prop ON prop.message_id = m.id > AND prop.person_id = 1 > WHERE 1 = 1 > AND NOT EXISTS(SELECT > * > FROM message_property pr > WHERE pr.message_id = m.id AND pr.person_id = > prop.person_id AND prop.is_read = TRUE) > ; > > The problem is that it's not quite efficient and performs badly, > explain analyze shows: [snip] > Does anyone have suggestions on how to optimize the query or schema? I'm getting better performance with: SELECT m.id AS message_id, 1 AS person_id, FALSE AS is_read, m.subject FROM message m WHERE 1 = 1 AND NOT EXISTS(SELECT * FROM message_property pr WHERE pr.message_id = m.id AND pr.person_id = 1 AND pr.is_read); You then lose the distinction between message_property with is_read = FALSE, and nonexistent message_property for the message row. If that is essential, I'm getting a roughly 2x speedup on my non-tuned PostgreSQL with: SELECT m.id AS message_id, prop.person_id, coalesce(prop.is_read, FALSE) AS is_read, m.subject FROM message m LEFT OUTER JOIN message_property prop ON prop.message_id = m.id AND prop.person_id = 1 WHERE not coalesce(prop.is_read, false); HTH, Jochem -- Jochem Berndsen | jochem@functor.nl -- Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-performance