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 1uT6Bg-00HPZO-D2 for pgsql-hackers@arkaria.postgresql.org; Sat, 21 Jun 2025 21:55:48 +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 1uT6Be-009X7a-EZ for pgsql-hackers@arkaria.postgresql.org; Sat, 21 Jun 2025 21:55:47 +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 1uT6Be-009X7S-28 for pgsql-hackers@lists.postgresql.org; Sat, 21 Jun 2025 21:55:46 +0000 Received: from mail-yw1-x112b.google.com ([2607:f8b0:4864:20::112b]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uT6Bc-003NOJ-1C for pgsql-hackers@lists.postgresql.org; Sat, 21 Jun 2025 21:55:46 +0000 Received: by mail-yw1-x112b.google.com with SMTP id 00721157ae682-70e77831d68so29059867b3.2 for ; Sat, 21 Jun 2025 14:55:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750542942; x=1751147742; darn=lists.postgresql.org; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=BzpPrjy1ZRsa6LsMpz68r+khUbccZU0gQzdwElDZa2w=; b=mIjo0evnFRQX0uMODLuZIx4gLVcf2DNm08+ugw1+OUbbZrgZTSuCjuLasfaTmLsdkq XUKY8tDZyQfNm9kuQ+WbWwOeoHCMV3X5LfESOI59BzrP8JE3jLYwtJ3Oxq6bbYkfJpH1 ydhQfjuJ3bdFw14mpCsRPab+C1Z+PQJr4HLXSxBkWA8SJ7RMYbGT0CTmLRFpJ3CVFxGv 0IAeN0cAVPn5DFX1jLfpY9/KJr59lTFqVgI9HuiEjzwEzxjNACmih73/O+8O6N46ekB9 tGEJorRlboum77v4B5nD7pOUaHFdt8TrtmH7uVpl61Z7Sbz5mZB4y/ebFF0zPwP33W7k 4WOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750542942; x=1751147742; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=BzpPrjy1ZRsa6LsMpz68r+khUbccZU0gQzdwElDZa2w=; b=J3uJYHhIyMUG6zZ5mBKcXchSc9dDrZ+j5lol6jdlgWL7nHlsyQKrd0UALOKtZJSiVc n172CZKwE5/EJbAOkNzh+v0H5ZA5OhV55xk/4rIubFmwnPvZMNcVkDJMnILpk69kayyU 3pVlPdAguGp/XNd/whixne0RoE7JtdvKtIhQgXoNF5CBFou61QTJhxnr6zp7XPlWbdN8 jP2RSs1yeZy3ZqUY82I0ebjSmfKiXLRshj1Hf+99RjDAIVhyHF0M4bXh2Ta5aHoUYhhc M4otmJxN+GdJWwj2lwyUTjcwwoiJgI0vgL6IY6+DmHHHAON8eQvxB2uSIYx/HmCo9ydE vZcA== X-Gm-Message-State: AOJu0Yxp58E0RtpDegK2wpqGR29qrrhfqM1BjqM5f3zOaJxPd4lz0XHh PYvTs56NvYAGchEsxVafe7Taz2DugGtz+9w6eZPhlcVAGzn2vVZo31DnYBUd2Ea0tczeCKrOfcN vaq+avvJu6E8lbFjHhWd8G2jjbVKJ5xKIlNukeHE= X-Gm-Gg: ASbGncty9Gc/xqCu31t8tcpfLKzdStJxNMUkvxw8FXuQbaXt/CNaOAlsF1v6y0bzvjU JNKVNhlfbdt7qKDzRXezn0qBHn7LcFH96eiXG4Q4Ho3GGk64Fv4A/EIWaOGrk2TYtwfBq5stW2/ 8K7Pi09dS1Ec2whZdGi8Vn9mHpLirDsIa621ckYyPlk1/G X-Google-Smtp-Source: AGHT+IGCtRlVLsI/kRYXL1/T0rdHZMVNEUG4iOSUTtkoyTTUBjBhL9DLOvt4Qk4Bwe6qrigaAB6TmI5Y/lyqrUbP4rk= X-Received: by 2002:a05:690c:4a04:b0:70d:f9ee:8b74 with SMTP id 00721157ae682-712c6387316mr104605647b3.7.1750542942117; Sat, 21 Jun 2025 14:55:42 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Arseniy Mukhin Date: Sun, 22 Jun 2025 00:55:31 +0300 X-Gm-Features: AX0GCFuBlMK1MIxjwep-gZpe8FKrlt8hywTPrJY2FSg5A8voy8Lu-JfpWyL-G2c Message-ID: Subject: Re: amcheck support for BRIN indexes To: PostgreSQL Hackers Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, I would like share some thoughts about 'heap all consistent' part and one of the open questions: The idea behind 'heap all consistent' is to use heap data to validate the index. BRIN doesn't store heap tuples, so there is no straightforward way to check if every tuple was indexed or not. We have range data, so we need to do something with every heap tuple and corresponding range. Something that will tell us if the range data covers the heap tuple or not. What options I see here: 1) We can use the addValue() function. It returns FALSE if range data was not changed (in other words range data already covers heap tuple data that we pass to the function). It's very easy to do, we can use heap tuples directly. But the problem I see here is that addValue() can return TRUE even if heap tuple data have been already covered by the range, but range data itself changed for some reason (some new algorithm were applied for instance). So I think we can have some false positives that we can do nothing about. 2) We can use the consistent() function. It requires ScanKey and returns true if the range data satisfies ScanKey's condition. So we need to convert every heap tuple into ScanKey somehow. This approach is implemented now in the patch, so I tried to describe all details about heap tuple to ScanKey conversion in the comment: /* * Prepare ScanKey for index attribute. * * ConsistentFn requires ScanKey, so we need to generate ScanKey for every * attribute somehow. We want ScanKey that would result in TRUE for every heap * tuple within the range when we use its indexed value as sk_argument. * To generate such a ScanKey we need to define the right operand type and the strategy number. * Right operand type is a type of data that index is built on, so it's 'opcintype'. * There is no strategy number that we can always use, * because every opclass defines its own set of operators it supports and strategy number * for the same operator can differ from opclass to opclass. * So to get strategy number we look up an operator that gives us desired behavior * and which both operand types are 'opcintype' and then retrieve the strategy number for it. * Most of the time we can use '='. We let user define operator name in case opclass doesn't * support '=' operator. Also, if such operator doesn't exist, we can't proceed with the check. * * Generated once, and will be reused for all heap tuples. * Argument field will be filled for every heap tuple before * consistent function invocation, so leave it NULL for a while. * */ With this approach function brin_check() has optional parameter 'consistent_operator_names' that it seems to me could be very confusing for users. In general I think this is the most complex approach both in terms of use and implementation. 3) The approach that seems to me the most clear and straightforward: to add new optional function to BRIN opclass API. The function that would say if passed value is covered with the current range data. it's exactly what we want to know, so we can use heap data directly here. Something like that: bool withinRange(BrinDesc *bdesc, BrinValues *column, Datum val, bool isnull) It could be an optional function that will be implemented for all core BRIN opclasses. So if somebody wants to use it for some custom opclass they will need to implement it too, but it's not required. I understand that adding something to the index opclass API requires very strong arguments. So the argument here is that it will let to do brin check very robust (without possible false positives as in the first approach) and easy to use (no additional parameters in the check function). Also, the withinRange() function could be written in such a way that it would be more efficient for our task than addValue() or consistent(). I'd be glad to hear your thoughts! Best regards, Arseniy Mukhin