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.96) (envelope-from ) id 1wcX9p-003Qf7-1j for pgsql-hackers@arkaria.postgresql.org; Wed, 24 Jun 2026 23:37:25 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wcX9n-0031UG-30 for pgsql-hackers@arkaria.postgresql.org; Wed, 24 Jun 2026 23:37:23 +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.96) (envelope-from ) id 1wcX9n-0031U8-20 for pgsql-hackers@lists.postgresql.org; Wed, 24 Jun 2026 23:37:23 +0000 Received: from mail-dl1-x122f.google.com ([2607:f8b0:4864:20::122f]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wcX9l-0000000067Q-3X3H for pgsql-hackers@postgresql.org; Wed, 24 Jun 2026 23:37:22 +0000 Received: by mail-dl1-x122f.google.com with SMTP id a92af1059eb24-139a5f4ca15so1855001c88.1 for ; Wed, 24 Jun 2026 16:37:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1782344241; x=1782949041; darn=postgresql.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id:from :to:cc:subject:date:message-id:reply-to; bh=1xnobI6wQT41Afp/i2mQUGlxKAWvZPkFSTC/1/hBmWI=; b=AwvRotnXmshCfDJOaRJzrv1em1k3akeWfc2kct33AH+qDfazTTQkydyI5dcBdb0p1n yX9Yia67eLEbOrdfwVwDBoOHG8dYhPgjCV931Pv5NjKBALSK3SV9clPkJr+x3OBG2Jgf nEZioeUBcvmHD9ieuBvkjZvIY1njri9KFN1aDWcBh2Dw5gXJ5qlSxXz1bJOjjFJWw7jx JAAtFx+LxoOhryzzwOSaO8OUsV0eRBuehq+mzjJYC/+fQPDUK7G7n2eYffmvOvmqx6jp zy/R6B+cNESRIknnCqk7OJvLLxpEXajtg85iWv+/TvjuB+/qUugDmjKdSquK6ijYDcWx pLIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782344241; x=1782949041; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=1xnobI6wQT41Afp/i2mQUGlxKAWvZPkFSTC/1/hBmWI=; b=lFWZxZWCSTOqVjzO8Bu7T/PVjWZFIIaeZbRVIXLdMWX1/DnEuCILku2Twzv9SwLJSw vO/+dZtgKAa6Yh5m1gVYsshi1N6qilBIge+MlWI1CAFmTAePF035ycAUx7EvHX49QIsS iQoPZKimLpc1EnLfAbanaoEXwfU13ReY1Njl0abEnna8+AafbP8SBkiYC00yn6PrcisS mv6fODbwXVmaenUIfhTRC0zjybzcbS99k8ttbnZAbUFnVoZTYdJ8ej59e8OR8NGrBcgB LNZbHW2g5qOLzFE/Y6daVN9hyuMLfahsN/tvTf60ByT/KbOErH5EePrP97mUMou8AseJ yQsg== X-Forwarded-Encrypted: i=1; AFNElJ+MVOiT8EX4oWEozUL5lmyFkjK2qjSNCN0c360wShsyNIWr3PcHIw73RNPtMkm7/CKBsr0kPMDaIzne50ri@postgresql.org X-Gm-Message-State: AOJu0YyCIHTHR3/r3ng4ITJfPewuxPFlf9S7i5T56W9RChVeQcJ8Vgz8 0WN3jqcfL4+AuPgSg34hNIA2ZLcqfDF5UzXPQB6Xl6XDNNd2r7+EDT7hndw3rTjc X-Gm-Gg: AfdE7ckiuigEQopaKIUcw/2Pe3lBCimxoEez24OWf0NUrwX4Awnx4KpXC5Crr+zp1JW 44L48MzUC1V5Rc4v8iM9oBogYcTwWMlkUj1yj+X/czvjX8pDE4rFrvm6WxNSjg3JNlgZ089/95y 6QIKLNM2Y0fphGDG9ZK5xXccny6gk3JbCGEwSgs46RE9j/i9bi4RpGZ/7mLa31zlhPviG7Ogcxx nKRaxR3jqY9bSRdQESeZlOdzugn+zaZSHKChvkeUXvVD3UW3/vxmu34XGEhsVRGQRQ0VjTO8ttg F0cIkXmJ/p+qjYnFL+vl92RC3DuT168EJgSgE5tBHiXBFkShEGCatGc+ykmXY7sPbX2XBiP88Mm ycw27jW3iZ8CMQ4cwVL3vWvNw3Hios0hpsrIa6hZveaQ5C1zpPwySY+sGKaVWGnTRq7Gir83Tk1 UqMbTtFnNnxzgWfZl9XyZA9KU51F3t7xOW/9S7P2+FbvuKtIImEOWB3JM= X-Received: by 2002:a05:7022:117:b0:137:f958:c072 with SMTP id a92af1059eb24-139dbac82b2mr137650c88.20.1782344240718; Wed, 24 Jun 2026 16:37:20 -0700 (PDT) Received: from ?IPV6:2620:149:13d0::289? ([2620:149:13d0::289]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-139d9105b57sm2274261c88.14.2026.06.24.16.37.20 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 24 Jun 2026 16:37:20 -0700 (PDT) Message-ID: <9a3604ae-b36d-492d-a74b-a3f57cdfd5ae@gmail.com> Date: Wed, 24 Jun 2026 16:37:19 -0700 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Adjusting hash join memory limit to handle batch explosion To: Tomas Vondra , PostgreSQL Hackers References: <7bed6c08-72a0-4ab9-a79c-e01fcdd0940f@vondra.me> Content-Language: en-US From: Ben Mejia In-Reply-To: <7bed6c08-72a0-4ab9-a79c-e01fcdd0940f@vondra.me> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 12/31/24 3:06 PM, Tomas Vondra wrote: > Hi, > > I've been once again reminded of the batch explosion issue in hashjoin, ... > > It's much worse when there's a batch that is not "divisible", i.e. > adding more batches does not split it roughly in half. This can happen > due to hash collisions (in the part that determines the batch), > duplicate values that didn't make it into MCV (and thus the skew > optimization does not kick in). > > This is fairly rare, but when it happens it can easily lead to batch > explosion, i.e. rapidly increasing the number of batches. We add > batches, but the batch does not split, so we promptly hit the limit > again, triggering another increase. It often stops only when we exhaust > the 32-bit hash space, ending with 100s of thousands of batches. ... > * It actually helps with the "indivisible batch" case - it relaxes the > limit, so there's a chance the batch eventually fits and we stop adding > more and more batches. With spill files that's not the case - we still > keep the original limit, and we end up with the batch explosion (but > then we handle it much more efficiently). The "indivisible batch" case is when all tuples end up in the same batch. This is directly analogous to having all the tuples in one hash bucket. In Postgres hash joins we're simply using different bits of the tuple's hash value to select batch and bucket. This can be addressed by the relax-the-limit approach Tomas describes in patch (1) of <7bed6c08-72a0-4ab9-a79c-e01fcdd0940f@vondra.me>, committed for PG18 as a1b4f28. But this can only do so much. In fact there's the comment in nodeHash.c: /* * If we dumped out either all or none of the tuples in the table, disable * further expansion of nbatch. This situation implies that we have * enough tuples of identical hashvalues to overflow spaceAllowed. * Increasing nbatch will not fix it since there's no way to subdivide the * group any more finely. We have to just gut it out and hope the server * has enough RAM. */ I tried the "loop over the inner side" as did Melanie in . I got correct results but the runtime was worse than the gut-it-out approach. There is another thing to try: a secondary hash. A secondary hash splits the batch when the tuples have distinct keys that collide in the hash (the common case). It can't split a batch that is one repeated key: equal keys hash equally. There we still fall back to the gut-it-out path. The point is that today we treat both cases identically, when only the duplicate-key case is truly unsplittable. (See Raghu Ramakrishnan and Johannes Gehrke. Database Management Systems. 3rd edition. McGraw-Hill, 2003. ISBN 0-07-246563-8. Chapter 14, "Evaluation of Relational Operators". Page 465) See for more information. Ben Mejia