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 1tbUba-00B5Ki-G8 for pgsql-hackers@arkaria.postgresql.org; Sat, 25 Jan 2025 01:04:58 +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 1tbUbY-000pT6-KZ for pgsql-hackers@arkaria.postgresql.org; Sat, 25 Jan 2025 01:04:56 +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.94.2) (envelope-from ) id 1tbUbY-000pSy-BN for pgsql-hackers@lists.postgresql.org; Sat, 25 Jan 2025 01:04:56 +0000 Received: from mail-ed1-x544.google.com ([2a00:1450:4864:20::544]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1tbUbV-001M3h-2T for pgsql-hackers@lists.postgresql.org; Sat, 25 Jan 2025 01:04:55 +0000 Received: by mail-ed1-x544.google.com with SMTP id 4fb4d7f45d1cf-5d3f65844deso4688144a12.0 for ; Fri, 24 Jan 2025 17:04:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737767093; x=1738371893; 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=EcyS18XzzmmarQPHzEigaP/TsgzZmxDlUqApHn/5Zr8=; b=Maoz6KdRSUewUJ0Bk5GrftbbQg1u/42jm4gaXkGt/7p8+xQ6uw/3mrXg9OLe9wxpUW A4eH/7ZhkMosqn4YuyxOKRmDhUBd9DPmRkxmh7675P9hn+diuY5mvGijjGVePhSP4q0s Ro3K9UtNc5f02Xc66+j40JDDnq5xih9S9bq4Cbz45c2KD62zj1jV+u6OWEnyb/1T3j1f +Ar14lvVT3rOfVOdDSw16ZIfPrGJfK0Zl5/3Hhh02e1DwMgIoK9Vpz4gKXML6kpVTse7 m0oB/IHZ0SGa+YqklD82WT5wdLWAWzYN0AcGIBz8YTWCUBGLXxSn4i/MnqEaf4SWGti+ OkvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737767093; x=1738371893; h=content-transfer-encoding:cc: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=EcyS18XzzmmarQPHzEigaP/TsgzZmxDlUqApHn/5Zr8=; b=gJhTXhOstzqy+HkgktNSRERIE/u0Zb3Gwy/0UaoOA9Wsu7imp8fVlfVTtzQbkojP90 P2eMOISJBYILjbYLMHcSqLarrEepaHe+jnTZvoXCJG29kNEvjK7apQGA3/6gHOtLiM+h +AYwinr2HNWzcuxmTXzriFySQ81x3xQfv5G90ciulcCNGj5Vt9BYRLGrj9O8vBYo6d9f hpDCq0ct0IZf88namMu3EQHSYW78GybiOWlAHAE8WAcWtmgkJY6OE7Tp5P5Zr/0lCepD Hab4LqEu9BC4wxtluY7YTsFqFF4F/gFYXYCPLirs/RT/FwvyVJbf/4cEa3uC+l9whxGR 5kPw== X-Gm-Message-State: AOJu0Yxn1XEzi990gMuDAkB59W4COsHsblvAIUjClQH7Ny8Iz3zHpJZ6 08w8Y1I8M0GvaCUD+VNV0JbmbWnBRLoWcME2D9bR+M+DmhQ+r4Vyk+4vfSEt5BTEJxA9ssEwA9+ ydFQSIx91dnYv/Oo/UZVBi+4hFqU= X-Gm-Gg: ASbGncuPGks+7xy8/OuOLv3zVdRJKsylSNDSj0gDHmm3cVETIGWvi83kFHwzoGE+0f4 oYET2v9Ac+I7wOfFXzOHfbbX6uZqNbAETWre5nerydSea/y0KFOkvkGqgzljDVOFp0QILTlhyuR c= X-Google-Smtp-Source: AGHT+IHa3AqTr3kux0Om+Z9G3lExPA8Qq7rosAL4BppKhs6kisspOtumQ7hC1ICQ9j9UNZN2GsPmG3vt+wE5UVFsXVI= X-Received: by 2002:a05:6402:51cb:b0:5d1:2631:b897 with SMTP id 4fb4d7f45d1cf-5db7d2f9f31mr26524960a12.14.1737767092386; Fri, 24 Jan 2025 17:04:52 -0800 (PST) MIME-Version: 1.0 References: <0beedccb92ba5a1db386bd09b44e15b20c1ac1fc.camel@j-davis.com> In-Reply-To: <0beedccb92ba5a1db386bd09b44e15b20c1ac1fc.camel@j-davis.com> From: James Hunter Date: Fri, 24 Jan 2025 17:04:40 -0800 X-Gm-Features: AWEUYZmCYCiJLWXB0kH4-ysm-0sy493ul8Ruk5jTy6bQBdER-GXoY6Jb7nQlgaA Message-ID: Subject: Re: Proposal: "query_work_mem" GUC, to distribute working memory to the query's individual operators To: Jeff Davis Cc: "pgsql-hackers@lists.postgresql.org" 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 Tue, Jan 21, 2025 at 1:26=E2=80=AFPM Jeff Davis wrot= e: > > On Fri, 2025-01-10 at 10:00 -0800, James Hunter wrote: > > How should =E2=80=9Cquery_work_mem=E2=80=9D work? Let=E2=80=99s start w= ith an example: > > suppose > > we have an OLAP query that has 2 Hash Joins, and no other operators > > that use work_mem. > > So we plan first, and then assign available memory afterward? If we do > it that way, then the costing will be inaccurate, because the original > costs are based on the original work_mem. > > It may be better than killing the query, but not ideal. As you point out, the outcome is better, but not ideal. My intuition is that an "ideal" solution would increase query compilation times beyond what customers would accept... But at least the outcome, if not ideal is better than killing the query! So it is a net improvement. > > I propose that we add a =E2=80=9Cquery_work_mem=E2=80=9D GUC, which wor= ks by > > distributing (using some algorithm to be described in a follow-up > > email) the entire =E2=80=9Cquery_work_mem=E2=80=9D to the query=E2=80= =99s operators. And then > > each operator will spill when it exceeds its own work_mem limit. So > > we=E2=80=99ll preserve the existing =E2=80=9Cspill=E2=80=9D logic as mu= ch as possible. > > The description above sounds too "top-down" to me. That may work, but > has the disadvantage that costing has already happened. We should also > consider: > > * Reusing the path generation infrastructure so that both "high memory" > and "low memory" paths can be considered, and if a path requires too > much memory in aggregate, then it would be rejected in favor of a path > that uses less memory. This feels like it fits within the planner > architecture the best, but it also might lead to a path explosion, so > we may need additional controls. > > * Some kind of negotiation where the top level of the planner finds > that the plan uses too much memory, and replans some or all of it. (I > think is similar to what you described as the "feedback loop" later in > your email.) I agree that this is complex and may not have enough > benefit to justify. Generating "high memory" vs. "low memory" paths would be tricky, because the definition of "high" vs. "low" depends on the entire path tree, not just on a single path node. So I think it would quickly lead to a state-space explosion, as you mention. And I think negotiation has the same problem: it's based on the entire tree, not just an individual path node. I think the general problem is not so much "top-down" vs. "bottom-up", as "individual path node" vs. "entire path tree." Today, PostgreSQL costs each path node individually, by referring to the static "work_mem" GUC. In any attempt to improve the optimizer's choice, I think we'd have to cost the entire path tree. And there are many more trees than there are tree nodes. For example, the decision whether to prefer a Nested Loop vs. a Hash Join that takes 2 MB of working memory, depends on what the query's other joins are doing. At any rate, I think we can solve the problem of "killing the query" now; and then worry, in the future, about the ideal solution of how to pick the optimal execution plan. > Regards, > Jeff Davis Thanks for your comments! James