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 1qHReF-0007b5-Up for pgsql-hackers@arkaria.postgresql.org; Thu, 06 Jul 2023 16:16:04 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1qHReE-00015g-Rc for pgsql-hackers@arkaria.postgresql.org; Thu, 06 Jul 2023 16:16:02 +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 1qHReE-00015X-EZ for pgsql-hackers@lists.postgresql.org; Thu, 06 Jul 2023 16:16:02 +0000 Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1qHReB-002NuV-Pq for pgsql-hackers@lists.postgresql.org; Thu, 06 Jul 2023 16:16:01 +0000 Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-3fbc0609cd6so9416035e9.1 for ; Thu, 06 Jul 2023 09:15:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cybertec-at.20221208.gappssmtp.com; s=20221208; t=1688660158; x=1691252158; 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=oAqsZWcu7qHGIz4W6f4w8lsZGgpM1dPywAeYYSfQaOA=; b=0fcZsLsdLaRJ6sUP4D1Pmrr3zHh8ZXo9nSeoJ8lNn6PWHxn0aDzRWWNmXyRiqzMioW F0KhLQIWT8htOYkZu5VsM0uBsDKUiKI6Fs0Ch2SyIrPxC1ZocwRbozL5jZwwFvhD1gj7 y3f0IZe6hTyAodqYW+7a7J0WXCjguQMVI6qC7J64uJ75rCqE4num4We89KFVt1QsMWXO oYbvXB/MTZhVhZUDeCmVQx86hWUH79h1qthmE9ZI61AfOE4KubrQDE6+z+g3rhurZj15 SKrXKhV0Pl/ZIqL5ijiEpp2z5Z6rAx/XA2RP5ZELI6MUjosuLSfEw1H8/Ns4CoZWpdH9 1/Dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688660158; x=1691252158; 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=oAqsZWcu7qHGIz4W6f4w8lsZGgpM1dPywAeYYSfQaOA=; b=Gu+Xc1K5q92bxkjyJ0aoXlpwPQ2q1VXTStmSl4Q8IOLsT1XrVPKBBk/LZWPcPgMnvV 6wHHsA3OMJS5CQQA/aEdnZdqTZXsng8vZmd8Rax6IWdnvyOncBvPiPCHKQCoI1hjzaZm U2nYgSFl7L5FDRM2tGfnirfB9kaf/j0iYhEMEAlTdt9I8CwpNyUD0NJeEAFxraEj01Cz RrPgCBBUKo0G4pgllXw6XNSxCv9lF6aRVUtDQ5sE9eMDrX/OLYHyKcp1boG/cYCqEEnV TRB3KLcm1hN/bSRDKksbeuCI6u+xUNNUPj1XQF+IpS0qXQY5lhI+PIv4zE8XQR5sWzBf KtTg== X-Gm-Message-State: ABy/qLZpFE3wfJygVyzV/PjxXFn32U8ocTWIW+r+FyVcnz++4EJf8LKD KgGZO2GsLYthe5a9lU7EWnWJl0sB5ixm40habzI= X-Google-Smtp-Source: APBJJlGVymIoa1NS/zX+HLSoE3St8erhal/XKu0/dvd+Nz3PkwIXH0Tunjn8pNdpv3vxPt8d06nb5A== X-Received: by 2002:a5d:4247:0:b0:314:2860:721f with SMTP id s7-20020a5d4247000000b003142860721fmr1883433wrr.15.1688660158031; Thu, 06 Jul 2023 09:15:58 -0700 (PDT) Received: from localhost.localdomain (62-46-248-159.adsl.highway.telekom.at. [62.46.248.159]) by smtp.gmail.com with ESMTPSA id a16-20020a5d5710000000b00314329f7d8asm2253848wrv.29.2023.07.06.09.15.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Jul 2023 09:15:57 -0700 (PDT) Message-ID: <4e6efd382b3195eb7ea438b7219cc94d9399c0bd.camel@cybertec.at> Subject: Re: [PATCH] Add support function for containment operators From: Laurenz Albe To: Kim Johan Andersson , pgsql-hackers@lists.postgresql.org Date: Thu, 06 Jul 2023 18:15:56 +0200 In-Reply-To: <94f64d1f-b8c0-b0c5-98bc-0793a34e0851@kimmet.dk> References: <94f64d1f-b8c0-b0c5-98bc-0793a34e0851@kimmet.dk> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.46.4 (3.46.4-1.fc37) MIME-Version: 1.0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Sat, 2023-04-29 at 17:07 +0200, Kim Johan Andersson wrote: > I had noticed that performance wasn't great when using the @> or <@=20 > operators when examining if an element is contained in a range. > Based on the discussion in [1] I would like to suggest the following=20 > changes: >=20 > This patch attempts to improve the row estimation, as well as opening=20 > the possibility of using a btree index scan when using the containment= =20 > operators. >=20 > This is done via a new support function handling the following 2 requests= : >=20 > * SupportRequestIndexCondition > find_index_quals will build an operator clause, given at least one=20 > finite RangeBound. >=20 > * SupportRequestSimplify > find_simplified_clause will rewrite the containment operator into a=20 > clause using inequality operators from the btree family (if available=20 > for the element type). >=20 > A boolean constant is returned if the range is either empty or has no=20 > bounds. >=20 > Performing the rewrite here lets the clausesel machinery provide the=20 > same estimates as for normal scalar inequalities. >=20 > In both cases build_bound_expr is used to build the operator clauses=20 > from RangeBounds. I think that this is a small, but useful improvement. The patch applies and builds without warning and passes "make installcheck-= world" with the (ample) new regression tests. Some comments: - About the regression tests: You are using EXPLAIN (ANALYZE, SUMMARY OFF, TIMING OFF, COSTS OFF). While that returns stable results, I don't see the added value. I think you should use EXPLAIN (COSTS OFF). You don't need to test the actual number of result rows; we can trust that the executor processes >=3D and < correctly. Plain EXPLAIN would speed up the regression tests, which is a good thing. - About the implementation: You implement both "SupportRequestIndexCondition" and "SupportRequestSimp= lify", but when I experimented, the former was never called. That does not surprise me, since any expression of the shape "expr <@ range constant" can be simplified. Is the "SupportRequestIndexCondition" branch dead cod= e? If not, do you have an example that triggers it? - About the code: +static Node * +find_index_quals(Const *rangeConst, Expr *otherExpr, Oid opfamily) +{ [...] + + if (!(lower.infinite && upper.infinite)) + { [...] + } + + return NULL; To avoid deep indentation and to make the code more readable, I think it would be better to write if (!(lower.infinite && upper.infinite)) return NULL; and unindent the rest of the code +static Node * +match_support_request(Node *rawreq) +{ [...] + switch (req->funcid) + { + case F_ELEM_CONTAINED_BY_RANGE: [...] + case F_RANGE_CONTAINS_ELEM: [...] + default: + return NULL; + } (This code appears twice.) The default clause should not be reachable, right? I think that there should be an Assert() to verify that. Perhaps something like Assert(req->funcid =3D=3D F_ELEM_CONTAINED_BY_RANGE || req->funcid =3D=3D F_RANGE_CONTAINS_ELEM); if (req->funcid =3D=3D F_ELEM_CONTAINED_BY_RANGE) { [...] } else if (req->funcid =3D=3D F_RANGE_CONTAINS_ELEM) { [...] } Yours, Laurenz Albe