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 1wILdA-0080Ic-16 for pgsql-hackers@arkaria.postgresql.org; Thu, 30 Apr 2026 07:16:16 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wILd9-006Zhw-1f for pgsql-hackers@arkaria.postgresql.org; Thu, 30 Apr 2026 07:16:15 +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.96) (envelope-from ) id 1wILd9-006Zhn-0c for pgsql-hackers@lists.postgresql.org; Thu, 30 Apr 2026 07:16:15 +0000 Received: from mail-wr1-x42e.google.com ([2a00:1450:4864:20::42e]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wILd6-00000003wW1-2im5 for pgsql-hackers@lists.postgresql.org; Thu, 30 Apr 2026 07:16:14 +0000 Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-43fde5b81a1so456735f8f.0 for ; Thu, 30 Apr 2026 00:16:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1777533371; cv=none; d=google.com; s=arc-20240605; b=dGsjyzZVioANmTGk1PFqu46hj9YxYe0ihx8yCGhm+jqCbOndbLg++VwATXhkTCgdpf rl2AqfGnu2CEuH6pIu3MKSdrjAQa22/zrW9xUIt1g0kgb3B53vXxFVIHv3VfX9zDhjSf r07KDqIWwts3kT60Pq/69Jo/WeE8k7FqDuj3cB4mueWi0DRmo7hp1fuhzXNnbaoHrlrq rCL+RlDMIhh1Upb2l2ksQ6GJdFlBsMBT8pv+a8NJ5VRk8zjMbmvhfz8YX8JGNMNS7D+i sy+S/wzHbnZSSyAbRxgV4a5PzW4FLovX/sm1u7pY0si9w5bE4YoY0DrN78j7y2dUVcT2 dsWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=NDUt4SG7j7RiseyRGoB5w5gQ1FZSudOBLWyBva4LgfU=; fh=PDhzRmLFhJQgKl2kpY6iqaoiggk+rKjB8rXL7ERgOws=; b=R0KSBGKUpEzAMlYgXhsL2tss76CaXLqLS6qpRxi9DjsW0Rz6x3qC62C0SuTqaY3taf GUNd0GZRjLORGvSe7AdOZ4UVTpVL5R0dIAty5B/DlAoEdEonIoSKQN56lMd2KkOYOg+h JcrqC9F4VYqUNspmTITeEs9QFc/r2yqpYneO+mGQCFZrOqBaTzFO7YjZoiUnKoJ2JppV ouqEHFmAnE3FLxu8kolzCxniuW4sg8P0k/xvxfarrjxjB8GmQZQNGqRfKEe01TjDYoOu or1JwulPSVLz9ZLFVzjR0L9glcSqHok/HicOjr3KIOz8dEQRVy08K55vIK15yeC3MJE8 l14A==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777533371; x=1778138171; 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=NDUt4SG7j7RiseyRGoB5w5gQ1FZSudOBLWyBva4LgfU=; b=FaDCZi4EJ3Vn0jxWR1xSuJQciugE8Gt6nh5SSAfADmjRQ3fUJ56GJzDJR5e0T9gbul G2/G6N80gwXXiEWB3DV8rKzqV7U3MhMf6ycDbWm7/h+UTVgm8tT0cQxytcXnrtzR7F9D IER709DFpcZd1j2oXlJ/tXzwbx/okqMABikvVifkoCD33EJSYjwCvOspBkSoxaocWKA3 4J3ibqKNfwjN3yyMr0Qc27dShfVorQ8zdDWA+/WZXabUqb0lOSk0UpGTanUyVEMEck2p uO/fOhtIHtEA+TPZPz6g+Ojn6gLXlU/Z7j7PiVwN2r36e3PZHkgWA9pIg2PYSoVmZGW9 wMPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777533371; x=1778138171; 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=NDUt4SG7j7RiseyRGoB5w5gQ1FZSudOBLWyBva4LgfU=; b=dsKtmGFarUgNpdLE2tdpGAP2PmsyXEvfO8PKCXDlLuS8nWY3VNQM55UZn/AEs+I9Y7 +OvH/Q4PEMcf6UzZExAAo5GKqcjykEPkbKHphQ3fUBR06beaJHh0XuXrBRdCKfB/XtKZ aakrRiNF3xryJ0Uza9ccwVUaX3U0R52vNJ5KTNNyX+e2QaCaZnitA6Uu1kbxiH9VPAxW ewW+h1Lp0dw3pj3yZ2PGiryG8fdDV2zis+YiU3yGS2K1hsF0RkXRaDfeeekpJQzURSd+ hu7cC68OFaPMfQYHmmrDdEJFLg14Z5RaRRoGMdvScqkIdhR6KvdQWVZQ6+m49UPy63nS oAQQ== X-Gm-Message-State: AOJu0YwDTYGSsTB7h7LOv0vcW/+TsqM7Sm7CcnCq6mKZbIVx5YSSYalE K7Gs2EgoS+NVXUlAZ74kTYERT0w7KiC+/Sd/AFhWt16Kd9Idd45jR3NlMHjCgP3T4Tj9elBVOfI Qr8+jAA6zKx7trMSzZOkfv1pG8fSUcso= X-Gm-Gg: AeBDietUPkDV1OMqSEuRILTGroGShyZ6fOhbn1CZWATqp/4YuJluzOf6OpgutWS6c6P jHyKhdp9hTVFinUP164jzmnBVMEBs6LM8BKQUehyICK6Er5TDts7h3zNZw5LTYWeEYoJlxNqHvK eSkY7x3XFk1ppjZ405fv8UmPT7WxWe0YxKjnC8VUAxgHUI3PWwUQq4xYxqtV/rRIhipaXA99YX2 +jaZoNEks8Qzmi/vyrzxoZWhaLAQy1GhPI3qGsLFhZk5fNi1h0E0EFgGj+Pm0R2Rfu1pu+zlTv6 02rlmZh5/MfyCF+KzUpVbdegwNEjfxNvDqPgUHnhgap5kTP+gkjNioAPAHbXQb1P X-Received: by 2002:a05:6000:2881:b0:43c:fc5c:aa0b with SMTP id ffacd0b85a97d-4493f42d6c2mr2501639f8f.42.1777533371205; Thu, 30 Apr 2026 00:16:11 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Ashutosh Bapat Date: Thu, 30 Apr 2026 12:45:57 +0530 X-Gm-Features: AVHnY4KUf_CccRtGkWQA9YlopJCl9MlwqMHM9ZSBl_i7wEPldqciocz_WnejW-w Message-ID: Subject: Re: Limit GRAPH_TABLE path combinations to prevent memory exhaustion To: SATYANARAYANA NARLAPURAM Cc: PostgreSQL Hackers 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 Wed, Apr 29, 2026 at 10:05=E2=80=AFPM SATYANARAYANA NARLAPURAM wrote: > > Hi hackers, > > generate_queries_for_path_pattern_recurse() enumerates all path > combinations by recursing over the Cartesian product of matching elements > per pattern position. Without IS label filters, each position matches > ALL tables of that kind, leading to N^K combinations (N tables, K > pattern positions). Each combination allocates a Query node via palloc > causing unbounded memory growth. > > A 8-table graph with a -element pattern reaches 81.3 GB RES in a few seco= nds > before I cancel the query. Tests in the patch (those were failed) can rep= roduce the problem > without the fix included in the patch. > > top - 15:04:19 up 43 days, 19:18, 5 users, load average: 0.43, 0.19, 0.= 08 > Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie > %Cpu(s): 0.9 us, 0.8 sy, 0.0 ni, 98.3 id, 0.0 wa, 0.0 hi, 0.0 si, = 0.0 st > MiB Mem : 515766.2 total, 248412.7 free, 234847.7 used, 48014.7 buff/cac= he > MiB Swap: 0.0 total, 0.0 free, 0.0 used. 280918.6 avail Me= m > > PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ CO= MMAND > 649642 azureus+ 20 0 212.2g 81.3g 33948 R 100.0 16.1 0:41.20 po= stgres > I tried to reproduce this problem on my laptop with queries included in the patch. For me all the queries finished. First within 4 ms, second within 133 ms and the third in 12ms. Did you try with more edges or more rows in the tables? > > As a POC I added a pre-computation check that calculates the total number > of path combinations before entering the generate_queries_for_path_patter= n_recurse. > If the product exceeds MAX_GRAPH_TABLE_PATH_COMBINATIONS (set to 10,000), > the rewriter reports ERRCODE_PROGRAM_LIMIT_EXCEEDED with a hint suggestin= g > IS label filters to reduce the search space. The limit of 10,000 is somew= hat arbitrary > but conservative. It caps memory at roughly 5 MB of Query nodes. > Patterns that would exceed the limit without labels can always be made to= succeed > by adding IS expressions to pin specific positions to fewer tables. > Alternatively, we can consider adding a GUC to control the limit but appe= ars > to be an overkill. Thoughts? I understand the problem and can understand the pain. Somebody who is writing a query like ()-()-()-()-() ... should know that every pattern that doesn't have a label will be matched against each vertex/edge. Our documentation makes it explicit [1] "The above patterns would match any vertex, or any two vertices connected by any edge ... ". But if they are really interested in matching every vertex or edge they don't have any other choice. Using restrictive label expressions would lead to wrong or incomplete results. If they can use label expressions they should do so anyway, otherwise they will end up with incorrect results. To me it seems like somebody who is writing such a pattern without providing enough resources is writing a bad query. We have other places where queries can consume large amounts of memory during planning or execution. Simply take the SQL query equivalent to the above pattern. We do not have a way to prohibit such queries as far as I know. I understand that SQL/PGQ makes it easy to write such queries by hand. But that seems to be abusing a powerful tool. Another example is joining partitioned tables with thousands of partitions. We have a GUC which enables or disables partitionwise join but there is no GUC to limit the number of tables or partitions being joined. I think we can document that such a pattern can result in large queries which may consume memory. Said that 81.3 GB looks unreasonably large for generate_queries_for_path_pattern_recurse() alone. I guess a large portion of it comes from planning and execution. How many rows did those tables had? Which phase of query execution consumed that much memory? Do you have a dump of memory contexts when it reaches that limit? [1] https://www.postgresql.org/docs/devel/queries-graph.html --=20 Best Wishes, Ashutosh Bapat