Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1vH6ly-00E0nb-9L for pgsql-performance@arkaria.postgresql.org; Thu, 06 Nov 2025 20:39:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1vH6lv-00ADFo-A2 for pgsql-performance@arkaria.postgresql.org; Thu, 06 Nov 2025 20:39:55 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1vH6lu-00ADFf-RP for pgsql-performance@lists.postgresql.org; Thu, 06 Nov 2025 20:39:54 +0000 Received: from mail-wr1-x435.google.com ([2a00:1450:4864:20::435]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vH6ls-005mSb-2c for pgsql-performance@lists.postgresql.org; Thu, 06 Nov 2025 20:39:53 +0000 Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-429ce7e79f8so39699f8f.0 for ; Thu, 06 Nov 2025 12:39:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bowt-ie.20230601.gappssmtp.com; s=20230601; t=1762461591; x=1763066391; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=bcBDv6hORnpVSEDAQ3ABFTXFeBp9Nd45CiqpG+itNFA=; b=QgbyT5L4pv3SzEs++ts8VgKpJMSXxuvry5cqWA0aRFYFNl/9WVNGIhfEMWx7/Yj1t8 tM2y9uw5Zegtol1EluEyvUPhXYvXIuqVB2x1m3+k5keFj6/DxdIIA3V34rkXqfDuecNA MJ8RlfzGVTwgftLHUjo86Xf43lDACqEFZR8k/LUaqzT8MmT3+Mz4zqGSiRj0RP9EU0L5 TwK4H/+WkX4Nm5V4+zh0aeFDDkAaAVrlLpexuzmW3p0A1hp0v4jrPAxeA6bDf/Cm9ve0 P27q8hFavOyGHqNk4B91h5HXo7qFGWsw/nwfNpx8i11YwPSWmVnXfysHbKP7Y/U40noh O1IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762461591; x=1763066391; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bcBDv6hORnpVSEDAQ3ABFTXFeBp9Nd45CiqpG+itNFA=; b=mX2JJ6ZkSpEKUv6aaqiClrLu2XGAoqnQrTpBlQeTTI542G4Kk2L3e4wPuQP+ZtfNeN /MSKIroADS2/WncPty+q0x3btFErGRT4iK02pcJwmR8c76XTxE/uE7zvgL5p2rOjJUvf /ss9TLfh/YinfHMYcZkdc+t/Z2BoCk+F1j+v+4gW/8oNDah/ymLlyf3t6xQ+QFRTzBMF UShS4oQhweNCTjWEKU1cIOyB07mCW2KmzkD/PGmUXrvEc2EYvgcahWTgeq3o4PkQ/PCN Jr/Y2qxQl9K7YkR2YjItwsP8odnbIIsAtpCXZ9E8MkY7IOa4SDXcJvzEesxlHLppkCvR jKpw== X-Gm-Message-State: AOJu0YyRz3UOKwnwNAgbbKATipdXLSaV3vajQB21CIXOdrLpvUOZtgGe rxG2aDOIaZyRxEHGoWlsjIGUfePB81KHunY952IYiONdBejYAqn/w8sbTa0Se+RM2MzjmHXQf6g D1txGxfsauKgJ6gyxwplEKncasp3HXshLTCkuTIuSuoAF+CnK/g+bBaxybA== X-Gm-Gg: ASbGncsPXjTEwocVBXg9bTdDhfCOS880wJbRcugASfBm91guuV9MGh7hUXJk86o/Ujm FIfy5xH6dTZL4Gw8nrNNal1RMilIc5r1vCNRHIwauT6F2vUeAf9LPwX9yT95CODBdZmCXuI2k8g Xz9MkyI1C0nQsmZHemfxwEm+0MkesNDYzN2J6pXiN0MM3/QgsQXtNdqwdzLNiJhR1sYVFpbFXxY Qz445ATi8bMiLAZTZGcn5aITp8wmyN4yKsPUIR7aKvpzyLlZnw8aplFY9vh4yU+AHFTpJA= X-Google-Smtp-Source: AGHT+IG6g0VN/Hbf0xSCf6L1eziDuYs09fUM8QFFIOX3VA69l63FMpFvrX1zP2mvOz2KunpNmDBmF6FsrerDwXjmOs8= X-Received: by 2002:a05:6000:26c9:b0:429:cf03:8b1a with SMTP id ffacd0b85a97d-42ae5ae9995mr482251f8f.45.1762461591318; Thu, 06 Nov 2025 12:39:51 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Peter Geoghegan Date: Thu, 6 Nov 2025 15:39:24 -0500 X-Gm-Features: AWmQ_blELteVjuahpbSx-oxsyuIgL_TWi71M0sMiaAohhKTTyI7aPsntaWzm9tk Message-ID: Subject: Re: Index Searches higher than expected for skip scan To: Michael Christofides Cc: pgsql-performance@lists.postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Thu, Nov 6, 2025 at 2:54=E2=80=AFPM Peter Geoghegan wrote: > That just leaves SK_ISNULL. We cannot assume that the index doesn't > have any NULLs (unless the query uses IS NOT NULL directly). Actually, that won't work here. Because the optimizer recognizes that the leading boolean column isn't nullable, and "helpfully" optimizes-away the IS NOT NULL qualification. But if the column *was* nullable, adding IS NOT NULL would cut the number of index searches by 1. > We might end up having to read the rightmost leaf page anyway, in which c= ase > there won't be an extra search for SK_ISNULL, but we'll likely need an > extra search for this too (just like the leftmost leaf page, with > SK_BT_MINVAL). I said the wrong thing here. In fact, it's very likely that we will have to read the rightmost leaf page with a query that has no qual on the leading column, no matter the datatype. Here's why: Suppose we only store tuples with the values 1 - 100 in the leading column "a", for a query "WHERE b =3D 5432", with an index on (a, b). Once skip scan reaches the point where it returns "(a, b) =3D (100, 5432)" to the scan (or once it sees that there's no such match in the index), it'll guess that the next "a" value is 101. We'll then try and fail to find a match "(a, b) =3D (101, 5432)". If the column "a" has no NULLs, then the scan will already be at the rightmost position of its rightmost leaf page -- so we're done then and there. Notice that there hasn't been an extra search for SK_ISNULL here. Because we visited the leaf page where NULLs would have been, had there been any, and found that there was none at all (which is the common case, contrary to what I said earlier). If, on the other hand, the column "a" has many NULLs, then this failed attempt to find "(a, b) =3D (101, 5432)" will advance the array on "a" from 101 to SK_ISNULL, and then perform another search, this time for "(a, b) =3D (NULL, 5432)". Again, notice that this also isn't wasteful -- we simply have no better way to reliably determine that there is no non-NULL value after 100 in this index. It's perhaps worth noting that your original boolean example shows that skip scan *is* directly aware that the next value after false is SK_ISNULL -- even though (as I said in my first email from earlier) it cannot do the similar trick of knowing that the lowest value really should be false (this is knowable before the first scan/search even begins). There are very obscure performance reasons for this inconsistency, though it might seem a bit arbitrary. --=20 Peter Geoghegan