Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lBmQF-0004Om-9R for pgsql-performance@arkaria.postgresql.org; Mon, 15 Feb 2021 22:32:51 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1lBmQC-0006VN-IH for pgsql-performance@arkaria.postgresql.org; Mon, 15 Feb 2021 22:32:48 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lBmQC-0006TK-6t for pgsql-performance@lists.postgresql.org; Mon, 15 Feb 2021 22:32:48 +0000 Received: from mail-il1-x135.google.com ([2607:f8b0:4864:20::135]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1lBmQ9-0002Pd-4p for pgsql-performance@postgresql.org; Mon, 15 Feb 2021 22:32:47 +0000 Received: by mail-il1-x135.google.com with SMTP id o7so6766750ils.2 for ; Mon, 15 Feb 2021 14:32:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=HYLq26D8Q3EPw9wuBTG0VfD8fuJaWgFcpg0QCZB4cS8=; b=d6PjcxGEJC2OVfKumPvNrFgM6HZugO7iVgyWwnNU2nBfRPDvpOOwkVBteIF7t6+/Jg Vpnl6L5qq3Lhk43zSxyx1JJHnYNDH0v/cbxnHmbmWb+YogWN8nUquTUJ8KGRInqL53QU UuKEqjfJGcf3/iUDE7dwGKsQa8U3b57U5WsCJaBG3r8LMD65QbaAGC68so4y7NN+zEMD kNNEQMrI8E2TMenASih0KQqDD20402UfdFdA3KbBEw6BVN1BKRLMcXzihk6Lwy1J46hb sr3ZjG2gAg5iU21jt8Z1wmsdryymoyaDwF+FwCdF/KpnYZD+bqrHyrM2knuDWmB3c5dq Dc1Q== 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:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=HYLq26D8Q3EPw9wuBTG0VfD8fuJaWgFcpg0QCZB4cS8=; b=g0CUo7YyFsxPWP/LYKxjYhFYxv1CMmhjA8sMZ8uJoTKTpp0Y04jvANHUlbTwaIOMyt 7Ij/Rz9pXPNmEUElEKkmNukxDix9haIhluwUqjICnYa3RYn2RTxmbubiUiLZnI2s6y4R E6PQp7Q82eOoDsxe3YVzZGYZ0nT6UfpVLXAfWZeJca2Qokz5r7vNuZjXHQCcPQr9GN/l uI1ePYxKN9tu1JFFqMpKhdWyuqc0sTAd/xW/K8XAfpHo1PJeRPvt6UgQjuic45Ig0Slq dAuZhehV7AYxQv6WLxLJZhw+GZLLq5WF7VXwrSGF1fInRaJ+ux2Fc74xuAFgX9ZqhR6X 2aFg== X-Gm-Message-State: AOAM532PtG0zlz5Xge+wa8ZR1brWs2EOcXFyYOCMM5k3o/78p+QxBiCO rP2dG2IFF4l2wXx8+iNuu1jKVg== X-Google-Smtp-Source: ABdhPJz6X3crl0f/xcM1URTepsOzIu+CtjXaLOK8EK8J+FdAFDiOL6S8zoocuegkz+DB0Y5y2US2Gw== X-Received: by 2002:a05:6e02:1848:: with SMTP id b8mr14195544ilv.210.1613428363094; Mon, 15 Feb 2021 14:32:43 -0800 (PST) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id g6sm9921691ilf.3.2021.02.15.14.32.42 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 15 Feb 2021 14:32:42 -0800 (PST) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id 38B948007F8; Mon, 15 Feb 2021 16:32:41 -0600 (CST) Date: Mon, 15 Feb 2021 16:32:41 -0600 From: Justin Pryzby To: Dane Foster Cc: psql-performance Subject: Re: Slow query and wrong row estimates for CTE Message-ID: <20210215223240.GE28165@telsasoft.com> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Mon, Feb 15, 2021 at 12:49:29PM -0500, Dane Foster wrote: > PostgreSQL version: PostgreSQL 12.5 on x86_64-pc-linux-gnu, compiled by gcc > (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11), 64-bit > EXPLAIN (ANALYZE, BUFFERS) > WITH max_spi AS ( Since v12, CTEs are usually inlined by default. I suspect it doesn't help, but as an experiment you could try WITH .. AS MATERIALIZED. You could try instead: CREATE TEMPORARY TABLE + ANALYZE, which will use statistics that "WITH" CTE's don't have (like the rowcount after GROUPing). > Aggregate (cost=672426.02..672426.03 rows=1 width=24) (actual time=903359.923..903368.957 rows=1 loops=1) > Buffers: shared hit=6167172 read=4199539, temp read=99551 written=99678 > I/O Timings: read=839121.853 This shows that most of time is spent in I/O (839s/903s) > -> Nested Loop (cost=672389.80..672425.91 rows=8 width=37) (actual time=36633.920..885232.956 rows=7034196 loops=1) > Buffers: shared hit=6167172 read=4199539, temp read=99551 written=99678 ... > -> Hash Join (cost=424676.58..671389.26 rows=1 width=24) (actual time=25169.930..34121.825 rows=833436 loops=3) > Hash Cond: ((attempt_scores_1.student_id = attempt_scores_2.student_id) AND (attempt_scores_1.assignment_id = attempt_scores_2.assignment_id) AND (attempt_scores_1.score_value = (max(attempt_scores_2.score_value)))) This shows that it estimated 1 row but got 833k, so the plan may be no good. As another quick experiment, you could try SET enable_nestloop=off. > -> Index Scan using for_upsert on attempt_scores (cost=0.43..36.42 rows=8 width=37) (actual time=0.394..0.896 rows=7 loops=938244) > Index Cond: (attempt_report_id = (max(attempt_scores_1.attempt_report_id))) > Buffers: shared hit=5976100 read=3869579 > I/O Timings: read=820910.987 This shows where most of your I/O time is from. I think you could maybe improve this by clustering the table on for_upsert and analyzing. Very possibly your "id" and "time" columns are all correlated. They might already/automatically be correlated - you can check the correlation stat: https://wiki.postgresql.org/wiki/Slow_Query_Questions#Statistics:_n_distinct.2C_MCV.2C_histogram Without looking closely, an index might help: student_id,assignment_id That'd avoid the sort, and maybe change the shape of the whole plan. -- Justin