Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1czBWk-0005QD-JP for pgsql-performance@arkaria.postgresql.org; Sat, 15 Apr 2017 00:25:22 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1czBWk-0003Wz-54 for pgsql-performance@arkaria.postgresql.org; Sat, 15 Apr 2017 00:25:22 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1czBUy-0000NM-P3 for pgsql-performance@postgresql.org; Sat, 15 Apr 2017 00:23:32 +0000 Received: from mail-io0-x232.google.com ([2607:f8b0:4001:c06::232]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84_2) (envelope-from ) id 1czBUt-0003qM-40 for pgsql-performance@postgresql.org; Sat, 15 Apr 2017 00:23:30 +0000 Received: by mail-io0-x232.google.com with SMTP id l7so119454656ioe.3 for ; Fri, 14 Apr 2017 17:23:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:subject:message-id:mime-version:content-disposition :user-agent; bh=uld9jqI3c5P2tA0ZA/iK3kr4rFO/HgkDJfOne8SaZTo=; b=vpaA7pXYtySL/mzTKDVsDtsv1WMFlF7XMpyB8IRC1/nqk75kPbXlj4nQDFZq37zGHd J5FG73cK3VY/FMLzHqKNIKPXYaKjNwa1oJ9eERdaZp6gKWcTMRBWTW/RTARbSIHFuJKz kyR8QHKhJtekrOvapiblprOvv3J6ZsMaKCYvBuF8AKj3yUkpdBx41t9Ad1Kc6p7dkdyi DHDkXfawQ2B7bXscSXqEd3ti8QTMRTn0huY7cI3ccmef0IZTfS0TLsfqTh9YUDBe8Y3/ 7WQEjUVoBNNcfnjdXChXauzs7Oq8NiFixzls9lhrNsSLGsfN4JVCs+HoiNXvchuDApAo NthQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mime-version :content-disposition:user-agent; bh=uld9jqI3c5P2tA0ZA/iK3kr4rFO/HgkDJfOne8SaZTo=; b=XhI9FIYHdHTBUT8St6teVyYnLaBeOIoy5MaXkc5FkPzj0S1grJTpFSbfuRb0OVPYtU ofZUaUDN1iGm4Icm2lQjk7FyOk/Ponb+X96ir+VVWzpRGd+aYgJeCIf9BuZ7Fg/UrWCS XINi65HPKcqA3ew9b7h6XFNlyAeJN1tmROgFflX9T85C7mRJ6b3bdRi1woc3DD4ObtHW 4CINo6PuHQkYpm4DvERGUoQIieo3BPkCTsz1omChA/FQ1wqYfRTZnHNZqZPRWBCrpLKi AlTYVPDHodP6M8h8ru9VQtZ77yooYva5JiCzs8SYo+jl7K+FMyw6t+jffq1/+BayWfgn Kq1A== X-Gm-Message-State: AN3rC/7XUzVkDk9QbYfL8xsoygwD81J6NzBUZDQH30kQP+1s2rbqw8AK R8sOItF2oznn4SYyVpI= X-Received: by 10.107.30.3 with SMTP id e3mr175744ioe.12.1492215804646; Fri, 14 Apr 2017 17:23:24 -0700 (PDT) Received: from pryzbyj (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id i189sm193513ita.23.2017.04.14.17.23.23 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Apr 2017 17:23:24 -0700 (PDT) Received: by pryzbyj (Postfix, from userid 1000) id 83CBD802020; Fri, 14 Apr 2017 19:23:22 -0500 (CDT) Date: Fri, 14 Apr 2017 19:23:22 -0500 From: Justin Pryzby To: pgsql-performance@postgresql.org Subject: self join estimate and constraint exclusion Message-ID: <20170415002322.GA24216@telsasoft.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) 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 I mailed last month [0] but didn't see any reponse .. (if I'm being naive, daft, or missing something simple, please just say so). [0] https://www.postgresql.org/message-id/20170326193344.GS31628%40telsasoft.com It seems when self (inner/equi) joining there's two bad alternatives: either specify a where clause for each self-joined table and incur poor estimate and plan, due to incorrect perceived independence of clauses, even though joined column(s) could/ought to be known equal; or, specify where clause only once, and incur cost of joining across all partitions, due to no contraint exclusion on one (or more) self-joined table heirarchy/s. -- Specify WHERE for each table causes bad underestimate: |ts=# explain analyze SELECT * FROM eric_enodeb_metrics a JOIN eric_enodeb_metrics b USING (start_time, site_id) WHERE a.start_time>='2017-03-19' AND a.start_time<'2017-03-20' AND b.start_time>='2017-03-19' AND b.start_time<'2017-03-20'; | Hash Join (cost=7310.80..14680.86 rows=14 width=1436) (actual time=33.053..73.180 rows=7869 loops=1) | Hash Cond: ((a.start_time = b.start_time) AND (a.site_id = b.site_id)) | -> Append (cost=0.00..7192.56 rows=7883 width=723) (actual time=1.394..19.414 rows=7869 loops=1) | -> Seq Scan on eric_enodeb_metrics a (cost=0.00..0.00 rows=1 width=718) (actual time=0.003..0.003 rows=0 loops=1) | Filter: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) | -> Bitmap Heap Scan on eric_enodeb_201703 a_1 (cost=605.34..7192.56 rows=7882 width=723) (actual time=1.390..14.536 rows=7869 loops=1) | Recheck Cond: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) | Heap Blocks: exact=247 | -> Bitmap Index Scan on eric_enodeb_201703_unique_idx (cost=0.00..603.37 rows=7882 width=0) (actual time=1.351..1.351 rows=7869 loops=1) | Index Cond: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) | -> Hash (cost=7192.56..7192.56 rows=7883 width=723) (actual time=31.620..31.620 rows=7869 loops=1) | Buckets: 8192 Batches: 1 Memory Usage: 1986kB | -> Append (cost=0.00..7192.56 rows=7883 width=723) (actual time=0.902..19.543 rows=7869 loops=1) | -> Seq Scan on eric_enodeb_metrics b (cost=0.00..0.00 rows=1 width=718) (actual time=0.002..0.002 rows=0 loops=1) | Filter: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) | -> Bitmap Heap Scan on eric_enodeb_201703 b_1 (cost=605.34..7192.56 rows=7882 width=723) (actual time=0.899..14.353 rows=7869 loops=1) | Recheck Cond: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) | Heap Blocks: exact=247 | -> Bitmap Index Scan on eric_enodeb_201703_unique_idx (cost=0.00..603.37 rows=7882 width=0) (actual time=0.867..0.867 rows=7869 loops=1) | Index Cond: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) -- Specify WHERE once gets good estimate, but with unnecessary scan of all child partitions: |ts=# explain analyze SELECT * FROM eric_enodeb_metrics a JOIN eric_enodeb_metrics b USING (start_time, site_id) WHERE start_time>='2017-03-19' AND start_time<'2017-03-20'; | Gather (cost=8310.80..316545.60 rows=9591 width=1427) (actual time=9012.967..9073.539 rows=7869 loops=1) | Workers Planned: 3 | Workers Launched: 3 | -> Hash Join (cost=7310.80..314586.50 rows=3094 width=1427) (actual time=8892.121..8937.245 rows=1967 loops=4) | Hash Cond: ((b.start_time = a.start_time) AND (b.site_id = a.site_id)) | -> Append (cost=0.00..261886.54 rows=2015655 width=714) (actual time=11.464..8214.063 rows=1308903 loops=4) | -> Parallel Seq Scan on eric_enodeb_metrics b (cost=0.00..0.00 rows=1 width=718) (actual time=0.001..0.001 rows=0 loops=4) | -> Parallel Seq Scan on eric_enodeb_201510 b_1 (cost=0.00..10954.43 rows=60343 width=707) (actual time=11.460..258.852 rows=46766 loops=4) | -> Parallel Seq Scan on eric_enodeb_201511 b_2 (cost=0.00..10310.91 rows=56891 width=707) (actual time=18.395..237.841 rows=44091 loops=4) |[...] | -> Parallel Seq Scan on eric_enodeb_201703 b_29 (cost=0.00..6959.75 rows=81875 width=723) (actual time=0.017..101.969 rows=49127 loops=4) | -> Hash (cost=7192.56..7192.56 rows=7883 width=723) (actual time=51.843..51.843 rows=7869 loops=4) | Buckets: 8192 Batches: 1 Memory Usage: 1970kB | -> Append (cost=0.00..7192.56 rows=7883 width=723) (actual time=2.558..27.829 rows=7869 loops=4) | -> Seq Scan on eric_enodeb_metrics a (cost=0.00..0.00 rows=1 width=718) (actual time=0.014..0.014 rows=0 loops=4) | Filter: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) | -> Bitmap Heap Scan on eric_enodeb_201703 a_1 (cost=605.34..7192.56 rows=7882 width=723) (actual time=2.542..17.305 rows=7869 loops=4) | Recheck Cond: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) | Heap Blocks: exact=247 | -> Bitmap Index Scan on eric_enodeb_201703_unique_idx (cost=0.00..603.37 rows=7882 width=0) (actual time=2.494..2.494 rows=7869 loops=4) | Index Cond: ((start_time >= '2017-03-19 00:00:00-04'::timestamp with time zone) AND (start_time < '2017-03-20 00:00:00-04'::timestamp with time zone)) Minor variations have same problems; -- Scans all partitions: ts=# explain analyze SELECT * FROM (SELECT * FROM eric_enodeb_metrics a) t1 JOIN (SELECT * FROM eric_enodeb_metrics b WHERE start_time>='2017-03-19 23:00:00' AND start_time<'2017-03-20') t2 USING (start_time, site_id); -- Underestimtes due to perceived independence of clause: |ts=# explain analyze SELECT * FROM (SELECT * FROM eric_enodeb_metrics a WHERE start_time>='2017-03-19' AND start_time<'2017-03-20') t1 JOIN (SELECT * FROM eric_enodeb_metrics b WHERE start_time>='2017-03-19' AND start_time<'2017-03-20') t2 USING (start_time, site_id); | Hash Join (cost=7308.59..14676.41 rows=14 width=1436) (actual time=30.352..64.004 rows=7869 loops=1) Thank you in advance for your any response. Justin -- Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-performance