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 1u9OfJ-001L1t-Gd for pgsql-performance@arkaria.postgresql.org; Mon, 28 Apr 2025 13:36:57 +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 1u9OeJ-0014yT-F2 for pgsql-performance@arkaria.postgresql.org; Mon, 28 Apr 2025 13:35:56 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1u9OeJ-0014yL-4R for pgsql-performance@lists.postgresql.org; Mon, 28 Apr 2025 13:35:56 +0000 Received: from mail-ej1-x62b.google.com ([2a00:1450:4864:20::62b]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1u9OeI-0000dx-0l for pgsql-performance@lists.postgresql.org; Mon, 28 Apr 2025 13:35:55 +0000 Received: by mail-ej1-x62b.google.com with SMTP id a640c23a62f3a-ac28e66c0e1so561250866b.0 for ; Mon, 28 Apr 2025 06:35:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cybertec.at; s=google; t=1745847353; x=1746452153; darn=lists.postgresql.org; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:from:to:cc:subject:date :message-id:reply-to; bh=WEnKgKPa/KA/+vIjBL4is1zLZL5ZYxgKZfRQt02GDq4=; b=qSwobM6PoCv33O4EgIoscs7IEAqBBZMtbMlfJfSbzY7Z/LLSJv4lZ51cyJabAxuO6H NFY3RvibUBrQYyfdnJHxCBMuFqXSxNOTQj0+RpyTaKq9v0JQWkXI6ijCnCy9fBCk81tC s2G8MbBSQckmNH4LkfHXovmO+J2xoj7/6OLGP1d7lqssNdtxlW0fAxbH0aUb7bdkWV3W UErQKxp4S3dPRZiZLnwCJiS9DQ/XjDKd/1Ib4uPngZwvt50T2hxCEoB+tNNiIjhL5DNC SP4E8JTz9buMSdSCBHZoQEDnISBbUCfjqUSueC+DzAemk4ewlJN/9OcFBHqasQoI7uzM fmPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745847353; x=1746452153; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=WEnKgKPa/KA/+vIjBL4is1zLZL5ZYxgKZfRQt02GDq4=; b=wakw/LxmbXA2Qdu2ATgC8kdGbtRGJbLh8Q7B4e+QY0oPAvkEVJy6c2nZZmKTmcGFn8 bULtC0FpNOGFdmp2wsZKDAYTneLKTF1KlFtfolWbVZ8K2o+Nks4PxRGKYzjTGJJgdTSz NP9JRcTrOkNyd2Ouzz5uxL+E4vQv/BZGSJcmxph6y/PgDe6VtcJRQ4apWHNZou2LZUr+ Zn1WF8YMC2w64W2mg3PD2TYbaAH5+yiGNzzcD7d4w5ObRsCaHxsQgk7IQkzlu+w5hIge yI4Dkp8df4lGZbYwXKkKPJGdvodLX6GDqTGgTlIqDJhelTz9TwbC/fHnvVMdHHXetiiP USug== X-Forwarded-Encrypted: i=1; AJvYcCXZ68PnBmNM5ykBUmq8zpgkLxR3D+h2ICtDdUawLW7tXoklqYYxzN/0fkws9oplbLgYjwdrLDJ15hURRokoCyJDMA==@lists.postgresql.org X-Gm-Message-State: AOJu0YwnGNd7bgQP3Ptz6TLhETNUNlXTvDhDfwIB5ezt9Q/AW/EuncOF uYD8qDFMRAGJalm79DoxfHdaoA5c1OtPhQl9L3QM6cIbzvO36AaR2sofAH4aVec= X-Gm-Gg: ASbGncsBGmYs7ELI2SSr7Qm5QwZP92diXbwvOQ9PJ1dvXn/LeuqDgYAiIIobEdLc/nf guk+WfveEsbqB1qpqJgzJm5vUrKr9EI3rm7gedlCUNSoOCpeoxiQgylUf2Jy3Z0INJupZ2gQhgf THB3acifNujOc0BwgRB7zbofFo/nDdQ0lSlhDIda22ErA5zfGi+JB7Qznj4hgxfN5O8u96fN9ti STxFSQ4LicsSQ4pnm8LWxy6UJWEnwkY5XF4C5M96dDtMTjk3MDiXPX2xcMYac4eogYfeltfvt07 I8J/bBRPVKRYdN7pfTjmjqmXqYgOsAbRm8b1ODhjtbLp28eMVQo/m79hMh0/qj/YjglC X-Google-Smtp-Source: AGHT+IFHSM5BqkDa/L/aDH1nsV06GF73jPph6uXOjxLLcb5W6sXlsIe1dgc07rB6xPUcLNUw9LuhCA== X-Received: by 2002:a17:907:9485:b0:ac7:75ce:c91d with SMTP id a640c23a62f3a-ace7108ac55mr1120121666b.15.1745847352647; Mon, 28 Apr 2025 06:35:52 -0700 (PDT) Received: from localhost.localdomain ([2001:871:5e:b56a:ce16:bfc1:eee:4d9]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ace6e41b80fsm626378466b.9.2025.04.28.06.35.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Apr 2025 06:35:52 -0700 (PDT) Message-ID: <79f3cb0ac1e221012df38d7baa72463662c37095.camel@cybertec.at> Subject: Re: PostgreSQL Choosing Full Index Over Partial Index From: Laurenz Albe To: Felipe =?ISO-8859-1?Q?L=F3pez?= Montes , pgsql-performance@lists.postgresql.org Date: Mon, 28 Apr 2025 15:35:51 +0200 In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.54.3 (3.54.3-1.fc41) MIME-Version: 1.0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon, 2025-04-28 at 15:22 +0200, Felipe L=C3=B3pez Montes wrote: > I am using=C2=A0PostgreSQL=C2=A017.4 on x86_64-pc-linux-gnu, compiled by = gcc (GCC) 12.4.0, 64-bit, > and working with the postgres_air Database. >=20 > I have a very simple query (please forget about the sense of the query it= self, > I just want to focus on the planner): >=20 > SELECT status > FROM postgres_air.flight > WHERE status =3D 'Canceled'; >=20 > And the following indexes: >=20 > CREATE INDEX flight_status_index ON flight(status) >=20 > CREATE INDEX flight_canceled ON flight(status) > WHERE status =3D 'Canceled' >=20 >=20 > Following the book PostgreSQL Query Optimization (Second Edition), there = is a > statement on page 90 talking about Partial Indexes that says that the pla= nner > will use the partial index rather than the full index on the flight table= , > however after doing my own tests I have checked that this is not true and= the > planner estimates that scanning the full index is cheaper than scanning t= he > partial one and would like to understand why. >=20 > I assume but might be wrong that having this partial index, lighter than = the > full table index, with both satisfying a specific index-suitable filter > condition (in this case canceled flights represent 171 rows vs 683178 row= s > from the whole table), should be a reason for the planner to know that > searching in the partial index should be faster than searching in the ful= l > index, besides the true fact that this partial index weights less than th= e > full one. >=20 > I also tried downgrading the version to the one used by the authors of th= e > book but same behavior happens. >=20 > Please see attached the different plan executions: >=20 > Plan for the full index: > > QUERY PLAN > Index Only Scan using flight_status_index on flight (cost=3D0.42..7.61 r= ows=3D182 width=3D11) (actual time=3D0.042..0.062 rows=3D171 loops=3D1) > =C2=A0=C2=A0Index Cond: (status =3D 'Canceled'::text) > =C2=A0=C2=A0Heap Fetches: 0 > Planning Time: 0.173 ms > Execution Time: 0.080 ms > > Plan for the partial index: >=20 > QUERY PLAN > Index Only Scan using flight_canceled on flight (cost=3D0.14..10.82 rows= =3D182 width=3D11) (actual time=3D0.039..0.050 rows=3D171 loops=3D1) > =C2=A0=C2=A0Heap Fetches: 0 > Planning Time: 0.135 ms > Execution Time: 0.066 ms Which index is bigger (you can use \di+ in "psql")? Could you run the pgstatindex() function from the "pgstattuple" extension o= n both indexes and compare the output? Does ANALYZE on the table make a difference? Yours, Laurenz Albe