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 1nucip-0006HH-95 for pgsql-performance@arkaria.postgresql.org; Fri, 27 May 2022 16:21:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1nucio-0002u2-6E for pgsql-performance@arkaria.postgresql.org; Fri, 27 May 2022 16:21:54 +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 1nuaBe-0008Nq-U2 for pgsql-performance@lists.postgresql.org; Fri, 27 May 2022 13:39:31 +0000 Received: from mail-lj1-x229.google.com ([2a00:1450:4864:20::229]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1nuaBc-00049I-9U for pgsql-performance@postgresql.org; Fri, 27 May 2022 13:39:30 +0000 Received: by mail-lj1-x229.google.com with SMTP id y28so142032ljd.4 for ; Fri, 27 May 2022 06:39:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dataegret-com.20210112.gappssmtp.com; s=20210112; h=to:from:subject:message-id:date:user-agent:mime-version :content-transfer-encoding:content-language; bh=fUVnzis3pGo729oxqO/9wkqA/24N1MWHb/DPBbqBf9E=; b=SlucLWTKwWBjuD11OOa24Idp3u8FE8tr6BgRxC5c1KJL86FhaQKSUxNMHSCbcuaRO7 5NZQEbxQqlFhTxTtv73VYQByCHkH9lME9nL3eB/KcrudEJGXItQbjBumXNBuy5Oamxv+ 0ouCW5kcWRN7VOCQXFAIhEK+GIYSIG0N0CsaNXmG7VtC6xpqWgKhyTeesipxu6nTD0eU jpcN7cfW1WsLbRFOno7898aeNGHmjQ1kXanw1A2nLV2kmeIgJ10N+hIVet/QHhXciMbR SNFdUbN0RFu1kkx4b/VBwtSoiePtDzNjxy6HoLUs+wP6W3dP2HuL78wi/h0lm7KMGfB9 dt8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-transfer-encoding:content-language; bh=fUVnzis3pGo729oxqO/9wkqA/24N1MWHb/DPBbqBf9E=; b=lYZzegdHeoIUndVkEbVxAygWHxOYKTX23nWnnhKIWT8ckm3wGbra6H4ZURQVNjGRU5 +UeZkkEpbGjGGfaCySJKFn3gMy/NytuCl6L8p13W7t6XQKKbxqmMK5vo8S3sILVcq1su +33T1ursOvqM3bGoh3PIppmZLV+NaThHKhH8gL20B6EXmCideY+fYiD666ZnqgaL9ouH bXKgTO8VY84ia8UESbCz8bmvbB0W5v1dP6zwFRtlwErqBwzFXiEKYaHL/2Zt5NgFtoN6 ezElrosnig44ixAag/PMZ6gqNUGji8os+GlOhs6LKls26DppW0X8EFYvPJ4hLMNZDVWF 0oZw== X-Gm-Message-State: AOAM532fvT94M4JHS2BB3B28Rg7sR77EONMb8LB3BTA5BN4Vyal7IBX2 LTZX11ADdTupF9lrFmRkRxJuoX5JEVZQ/w== X-Google-Smtp-Source: ABdhPJz98hKnDYqKOk8GLdlnGuUfsBXLVlVKHAfuHx1hvhffHUiLcfrpj0Bm1A+Gg/08cZ3WWxMkGg== X-Received: by 2002:a2e:981:0:b0:253:d97f:9686 with SMTP id 123-20020a2e0981000000b00253d97f9686mr23520891ljj.227.1653658764802; Fri, 27 May 2022 06:39:24 -0700 (PDT) Received: from iMac.local ([213.87.224.96]) by smtp.googlemail.com with ESMTPSA id u6-20020ac258c6000000b0047255d210d8sm882529lfo.7.2022.05.27.06.39.23 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 27 May 2022 06:39:24 -0700 (PDT) To: pgsql-performance@postgresql.org From: Alexey Ermakov Subject: rows selectivity overestimate for @> operator for arrays Message-ID: <744e32e4-eb37-ad43-250b-11494b199a9b@dataegret.com> Date: Fri, 27 May 2022 19:39:22 +0600 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.0; rv:68.0) Gecko/20100101 Thunderbird/68.12.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hello, please look into following example: postgres=# create table test_array_selectivity as select array[id]::int[] as a from generate_series(1, 10000000) gs(id); SELECT 10000000 postgres=# explain analyze select * from test_array_selectivity where a @> array[1];                                                          QUERY PLAN -----------------------------------------------------------------------------------------------------------------------------  Seq Scan on test_array_selectivity  (cost=0.00..198531.00 rows=50000 width=32) (actual time=0.023..2639.029 rows=1 loops=1)    Filter: (a @> '{1}'::integer[])    Rows Removed by Filter: 9999999  Planning Time: 0.078 ms  Execution Time: 2639.038 ms (5 rows) for row estimation rows=50000=10000000*0.005 we are using constant DEFAULT_CONTAIN_SEL if I'm not mistaken. and we're using it unless we have something in most_common_elems (MCE) in statistics which in this case is empty. if we have something in MCE list then we could use much better estimate (https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/array_selfuncs.c#L628): elem_selec = Min(DEFAULT_CONTAIN_SEL, minfreq / 2) for small tables we could get away with larger stats target for column, but for example in this case stats target 10000 is not enough. if I'm reading sources correctly element frequency in sample should be more than 0.0063/stats_target to make it into MCE list: https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/utils/adt/array_typanalyze.c#L471 so if we store mostly one element in array and they're almost all distinct then in tables with more then stats_target/0.0063 (~1.58M for maximum stats target 10000) rows we'll get 0.005 constant for selectivity. which could be pretty bad estimate (in real example it was 6-7 orders of magnitude difference). I ran into this issue 2 times in last year with 2 different projects so perhaps it's not very rare situation. In first case increasing stats target helped, in second it didn't (for table with 150M rows), had to use hacks to fix the plan. It was in PostgreSQL 12.x and 14.3. I'm not sure if there is a simple fix for this, maybe store and use something like n_distinct for elements for selectivity estimation ? or perhaps we should store something in MCE list anyway even if frequency is low (at least one element) ? -- Thanks, Alexey Ermakov