Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1aPdQM-0002fA-UL for pgsql-performance@arkaria.postgresql.org; Sat, 30 Jan 2016 21:51:19 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84) (envelope-from ) id 1aPdQM-0002sH-Fs for pgsql-performance@arkaria.postgresql.org; Sat, 30 Jan 2016 21:51:18 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84) (envelope-from ) id 1aPdQL-0002rq-L9 for pgsql-performance@postgresql.org; Sat, 30 Jan 2016 21:51:17 +0000 Received: from mail-wm0-x22b.google.com ([2a00:1450:400c:c09::22b]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84) (envelope-from ) id 1aPdQH-0008Rq-OO for pgsql-performance@postgresql.org; Sat, 30 Jan 2016 21:51:16 +0000 Received: by mail-wm0-x22b.google.com with SMTP id 128so24550532wmz.1 for ; Sat, 30 Jan 2016 13:51:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to:content-type:content-transfer-encoding; bh=CIrQBUlyyPy34H+E7TAVRQbLyXpvf/QV28eHfm3hVs0=; b=AJI4ZirFOiGtVmpvQrhpD1QvVA7E05TbALLVdr+NL0YtLuQO5YJV4Ms92eTuMFCAhJ Fy8LBJ0fOZlJdfo4kHTAcBSbCuX9z6O3jE8IvBQ6vK9GyHAjceddnhXhQYclDUrA+8a7 pH84K0MNqigULFAhLPVgAfxMpUdcvT1HoXSKrlA75nG4C9wEomqk+bvb6ycYt/A57phI ZH1xRt0DYLhnPJ1dmaesXX5OjS+G1ZzRbptxRvegNyAA2GUwUC8z/9rfUYSvTebC4kbb KevBMjKw0ly6Md6IPmzB0maYaN4CvGTBIbEk+eb/oS2BSccPgjBCXiDMtXsukozShGo9 faiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:subject:to:references:cc:from:message-id :date:user-agent:mime-version:in-reply-to:content-type :content-transfer-encoding; bh=CIrQBUlyyPy34H+E7TAVRQbLyXpvf/QV28eHfm3hVs0=; b=RWDgfkbYBaio71J1OV8Roy/k7Zd/mWOU5SXlnEvMPb7loZQkrkDf3I45WVK3NjER+S Yh9HZs0eSa3Y/fGKUk+IoeE+cMYYbvdRBmCFz64soOG+OmuXDU8KjLvmW1TV5WHIbK/U MyfQdmj+AoD9dcaw1qsyKCqzZUhZ5h7HBIexRH1k/xyHoTOQyw9kOYdv70JPMjvtm+4n VCE3SxHcCqzD1Sn6m98hdqUJBHEdOx/rFtowLRtPakgW7+ztftajB+8gJLLjf4QhA1ev OGWHC/Uh+Dx1LB9r11c7tTgI1GO7pEc3P/fof+MUCF+3SBSlTeKV+p6d/+PnCbkDDeSB zzWg== X-Gm-Message-State: AG10YOTGQYXPr5odtdhImDwQ43KlRYlkpHc9/tlWaHUBQsP9IiWqx8I4PTXnhrFRfr7IkA== X-Received: by 10.28.178.206 with SMTP id b197mr3938957wmf.72.1454190671296; Sat, 30 Jan 2016 13:51:11 -0800 (PST) Received: from hvlap.hvnet ([2.145.59.230]) by smtp.gmail.com with ESMTPSA id y8sm4130831wmg.9.2016.01.30.13.51.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 30 Jan 2016 13:51:10 -0800 (PST) Subject: Re: PostgreSQL seems to create inefficient plans in simple conditional joins To: David Rowley References: Cc: postgres performance list From: Hedayat Vatankhah Message-ID: <56AD303D.8090800@gmail.com> Date: Sun, 31 Jan 2016 01:20:53 +0330 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Pg-Spam-Score: -2.7 (--) 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, /*David Rowley*/ wrote on Sun, 31 Jan 2016 04:57:04 +1300: > On 31 January 2016 at 01:30, Hedayat Vatankhah wrote: >> Personally, I expect both queries below to perform exactly the same: >> >> SELECT >> t1.id, * >> FROM >> t1 >> INNER JOIN >> t2 ON t1.id = t2.id >> where t1.id > -9223372036513411363; >> >> And: >> >> SELECT >> t1.id, * >> FROM >> t1 >> INNER JOIN >> t2 ON t1.id = t2.id >> where t1.id > -9223372036513411363 and t2.id > -9223372036513411363; >> >> Unfortunately, they do not. PostgreSQL creates different plans for these >> queries, which results in very poor performance for the first one compared >> to the second (What I'm testing against is a DB with around 350 million >> rows in t1, and slightly less in t2). >> >> EXPLAIN output: >> First query: http://explain.depesz.com/s/uauk >> Second query: link: http://explain.depesz.com/s/uQd > Yes, unfortunately you've done about the only thing that you can do, > and that's just include both conditions in the query. Is there some > special reason why you can't just write the t2.id > ... condition in > the query too? or is the query generated dynamically by some software > that you have no control over? I can, but it would make my application code much more complex. I was hoping to be able to hide the complexity of DB data model in DB itself using views, triggers etc. If I want to add such conditions, the query generator in my application code would be more complex, and certainly the internal structure of DB will be visible to it. I'm working to re-design a DB which can grow large and slow, as I guess that we can find a more optimal design before trying optimizations like using materialized views and other common optimizations. I've found two completely different approaches for such problems: de-normalizing data, highly normalizing data (6NF) like Anchor Modeling approach. I decided to experiment with something similar to the latter one (not that extreme!) specially since our current design was not that normalized, and it performs poorly. I'm investigating why it should perform so bad with my queries, and this problem was one of the reasons. In such a design, views are used to present the JOIN of many tables as a single table, so that using the model is easy and transparent. But usually a single table doesn't have 10 ID columns (which can change as the model changes) for which you should repeat any conditions to get acceptable results! While it can be done, it is so annoying: the application should know how many tables are joined together, and repeat the condition for all such columns. And the problem become worse when you are going to create a relation between two different IDs of different data, e.g. relating customer info (composed of joining 5 tables) with info about items (s)he bought (composed of joining 3 tables). Anyway, it seems that this is what I should implement in my application code. I just hope that adding explicit conditions for each joined table will not turn off any other optimizations! Such an optimization seemed so natural to me that I didn't believe that PostgreSQL doesn't understand that a condition on ID applies to all id columns in a JOINed query, that I simplified my query step by step until I reached the minimum problematic query which is very similar to the one I posted here. It was at this point that I finally realized that maybe PostgreSQL really doesn't understand it, and I was ... shocked! > I'd personally quite like to see improvements in this area, and even > wrote a patch [1] which fixes this problem too. The problem I had when > proposing the fix for this was that I was unable to report details > about how many people are hit by this planner limitation. The patch I > proposed caused a very small impact on planning time for many queries, > and was thought by many not to apply in enough cases for it to be > worth slowing down queries which cannot possibly benefit. Of course I > agree with this, I've no interest in slowing down planning on queries, > but at the same time understand the annoying poor optimisation in this > area. > > Although please remember the patch I proposed was merely a first draft > proposal. Not for production use. > > [1] http://www.postgresql.org/message-id/flat/CAKJS1f9FK_X_5HKcPcSeimy16Owe3EmPmmGsGWLcKkj_rW9s6A@mail.gmail.com#CAKJS1f9FK_X_5HKcPcSeimy16Owe3EmPmmGsGWLcKkj_rW9s6A@mail.gmail.com > That's great, I might consider experimenting with this too. Regards, Hedayat -- Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-performance