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 1kHy6P-00064N-Aj for pgsql-performance@arkaria.postgresql.org; Mon, 14 Sep 2020 23:41:41 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kHy6O-0003BB-1i for pgsql-performance@arkaria.postgresql.org; Mon, 14 Sep 2020 23:41:40 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kHy6N-0003B3-MX for pgsql-performance@lists.postgresql.org; Mon, 14 Sep 2020 23:41:39 +0000 Received: from mail-il1-x144.google.com ([2607:f8b0:4864:20::144]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1kHy6L-0002rG-0r for pgsql-performance@postgresql.org; Mon, 14 Sep 2020 23:41:38 +0000 Received: by mail-il1-x144.google.com with SMTP id h11so1245671ilj.11 for ; Mon, 14 Sep 2020 16:41:36 -0700 (PDT) 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=QLVzF/irq/+pdz4J9egtP4CNSC2qgLw2P0hFdx2jIRc=; b=ge/yv1Q1B7GL9RoYkToxXy2+QfgVymM5D0ER50+afiV7CRdE+ajB/xXoJEt1rhWehi 3UZrVpnhnSPgOhPfjXP6Wgyg62v+cjnK8mHikEG2yUnx9T1hrCOJIWpuZIARPfwsjBXh AgvKz+9gVr125UAj8OWlOM+NNlnEkLvJlzaVcYWvZxr2uAi+YuNKurYXCRkcDi1tcGee cKSvkgKCbwwLFcDBSM8KnjFYbmqPfqLblxp+LyNEDc5eKp3mvoTQrarszohElTJYxT7L 68haVXIX7H19NUPqEkrz858RfOPpRUGGPlmqnORYxjcr67fHAD+mbJy71zo1J2JL9GXO lOdg== 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=QLVzF/irq/+pdz4J9egtP4CNSC2qgLw2P0hFdx2jIRc=; b=DY9FxwxpWq4Bl3EdYV/uGbSlRQDARq2iivVKOFpOPyyAroCbOwF6vm28SUT2Cj2Pcr NH7tCUwTw/2sW3juVaUHeLv/dfgT+sqaLdroK5i7qlK6/zBQifD/cP3kx9J2kx0gGOJV EbYwbI7KbzQN/fJOl+MRF5yiRcboaD4AIK9mm1I6bG8ULbDbPEWZ6QCRb8Vr+SfYTKRu ZX+9cvQwfyQAOca97bTVMWS/RxBShLdvQ7IHpHyWxVQFW0Hv/nr2uVdW1XGiRspIyJpI bi0pU7GUwkKQ9/MBBqtzOizDskZ31pWksyNn4UHr9XyenetV8ceN2/efnFYoS/v1iTqL F1nA== X-Gm-Message-State: AOAM5301c9Z2uMhgUeEP8I9bajqqZG1bb+O8KYV0b4izf3f3alzHD7bC VqjpuPkInNMcH/VCDMd4m5R8YRg/Rpsp3g== X-Google-Smtp-Source: ABdhPJy+81sB4NS/bGxAO4w9kzQjzyYy2MRPP1ynOb2/KOYPFinzKEVrmq+tsQIPrvpN8RJzmKy5bg== X-Received: by 2002:a92:cb01:: with SMTP id s1mr6271030ilo.225.1600126895728; Mon, 14 Sep 2020 16:41:35 -0700 (PDT) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id e4sm6663486iom.14.2020.09.14.16.41.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Sep 2020 16:41:35 -0700 (PDT) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id 3FEB4800159; Mon, 14 Sep 2020 18:41:32 -0500 (CDT) Date: Mon, 14 Sep 2020 18:41:32 -0500 From: Justin Pryzby To: Robert Treat Cc: pgsql-performance@postgresql.org Subject: Re: autoanalyze creates bad plan, manual analyze fixes it? Message-ID: <20200914234132.GF18552@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, Sep 14, 2020 at 07:11:12PM -0400, Robert Treat wrote: > Howdy folks, > > Recently i've run into a problem where autoanalyze is causing a query > plan to flip over to using an index which is about 10x slower, and the > problem is fixed by running an alayze manually. some relevant info: I think it's because 1) the costs and scan rowcounts are similar ; and, 2) the stats are probably near some threshold which causes the plan to change. I'm guessing if you run a manual ANALYZE 100 times, you'll sometimes get the bad plan. Maybe depending on the data visible at the time analyze is invoked. > UPDATE sleeping_intents SET > raptor_after='2020-09-14T19:21:03.581106'::timestamp, > status='requires_capture', > updated_at='2020-09-14T16:21:03.581104+00:00'::timestamptz WHERE > sleeping_intents.id = 'r2d2dcc0-8a44-4d19-c3p0-28522233b836'::uuid AND > sleeping_intents.status = 'finna' RETURNING *; Do you mean status='init' ?? > The plan generated after autoanalyze is: > > Update on sleeping_intents (cost=0.70..7.11 rows=1 width=272) (actual time=57.945..57.945 rows=0 loops=1) > Buffers: shared hit=43942 > -> Index Scan using sleeping_intents_status_created_at_raptor_after_idx on sleeping_intents (cost=0.70..7.11 rows=1 width=272) (actual time=57.943..57.943 rows=0 loops=1) > Index Cond: (status = 'init'::text) > Filter: (id = 'r2d2dcc0-8a44-4d19-c3p0-28522233b836'::uuid) > Rows Removed by Filter: 1262 > Buffers: shared hit=43942 > Planning time: 0.145 ms > Execution time: 57.981 ms > > after i run analyze manually, the query plan is changed to this: > > Update on sleeping_intents (cost=0.57..8.59 rows=1 width=272) (actual time=0.023..0.023 rows=0 loops=1) > Buffers: shared hit=7 > -> Index Scan using sleeping_intents_pkey on sleeping_intents (cost=0.57..8.59 rows=1 width=272) (actual time=0.022..0.022 rows=0 loops=1) > Index Cond: (id = 'r2d2dcc0-8a44-4d19-c3p0-28522233b836'::uuid) > Filter: (status = 'init'::text) > Rows Removed by Filter: 1 > Buffers: shared hit=7 > Planning time: 0.092 ms > Execution time: 0.066 ms > > Note that in the second query, it switches back to using the primary > key index, which does seem like the logically better choice, even > though it shows a higher estimated cost than the "bad" case > (understanding the cost must change somewhere in the process, but > there no way to see it afaict). If you SET enable_indexscan=off you can try to get an bitmap index scan, which will reveal how much of the cost is attributed to the index component and how much to the heap. That might help to refine costs, which may help. > Statistics after manual analyze: > tablename | attname | null_frac | avg_width | > n_distinct | correlation | most_common_freqs > -----------------+---------------+-----------+-----------+------------+-------------+-------------------------------------------------------- > sleeping_intents | id | 0 | 16 | -1 > | -0.00133045 | [null] > sleeping_intents | status | 0 | 9 | 6 > | 0.848468 | {0.918343,0.0543667,0.0267567,0.000513333,1e-05,1e-05} > sleeping_intents | created_at | 0 | 8 | -1 > | 0.993599 | [null] > sleeping_intents | raptor_after | 0.0663433 | 8 | -0.933657 > | 0.99392 | [null] > > In a previous go around with this table, I also increased the > statistics target for the id column to 1000, vs 100 which is the > database default. What about status ? I wonder if sometimes the sample doesn't include *any* rows for the 1e-5 statuses. So the planner would estimate the rowcount based on ndistinct and the other frequencies. But if you rerun analyze, then it thinks it'll get one row based on the sampled frequency of status. What postgres version, and what non-default settings ? Maybe you can run explain(settings,...). -- Justin