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 1vQsnj-001eWi-1F for pgsql-performance@arkaria.postgresql.org; Wed, 03 Dec 2025 19:46:11 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vQsni-00Fpd1-0Y for pgsql-performance@arkaria.postgresql.org; Wed, 03 Dec 2025 19:46:10 +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 1vQsnh-00Fpct-2f for pgsql-performance@lists.postgresql.org; Wed, 03 Dec 2025 19:46:10 +0000 Received: from mail-lf1-x132.google.com ([2a00:1450:4864:20::132]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vQsnf-002yRC-2X for pgsql-performance@lists.postgresql.org; Wed, 03 Dec 2025 19:46:09 +0000 Received: by mail-lf1-x132.google.com with SMTP id 2adb3069b0e04-594270ec7f9so72300e87.3 for ; Wed, 03 Dec 2025 11:46:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764791166; x=1765395966; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=XpeyMfYgmfPvpHQkkgD1jpdJRBGeEc3EImCDzFWPCCc=; b=JlGH5p0iIg07EoaRBT1OUjy94hKNuYvk5cL2PgjZQ2733znIC5CQLPwMbJh3d7XrI4 BUgRghZ120NYqe35kCZp9o7J/Y4VIhSAFYdHO0cIfgubXW4OGx36Bhh+CjoDVwdD0TKy 2S+QmOLXYLZ+QGccTW6Tfd1WTOrNLncULUp0Fwx4nXW8qrPVUlBZOG452EImRyA17rxv TYkt/CT9kWrLYQu2wNKdPWUvXFflqunpZvc3+7uO4Bx/agNfRYYfWsQu5pEXf6VdYMz0 9QAazidlj2kKc0vxF4NlTIfIOVtV0QqfL9uthiVffkWlHntnTZoYBWzYByVPs/2GZliN vXOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764791166; x=1765395966; h=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=XpeyMfYgmfPvpHQkkgD1jpdJRBGeEc3EImCDzFWPCCc=; b=oV+2d4bBsHL0UXMpwH2hDgxFFf3lz8kBQHUo45u/AuZxHhZc2IJZRVN9ssaprn+90o BXzhiy7j7KsqEiCMhJYFZ1BjrrDb22gEuKyvhm9bNN+ueMRokYER7oFuOEXKS3xlsFvZ d2e/ePrsgbmStS9oa/AuPB/NzuZfHA86MAOQAqrYeImzn2RXrefJPFZ3ZVJd4sSwdqpX kEF6MetRoKcl9ghNIep8IbtlXTacFF9SXh2eJ9l6lDxYT9Zv7QrbkdcMxMSsRPp7HcSY b8kmRSn2wAoBzwaWGNEGm+SeFK1mc6plZkd0LmhUbtZgsYarfkQ1yHxhCdDb9OEW+fgP Q7NQ== X-Gm-Message-State: AOJu0YwCEQqJKKPPZMoL2Pb1gPMkmcN3B15jACgY44m2uuN4qQFXnElA 6Zcs5o/Oxv7bq2r4nxAdrznLpt7hyGnk5d8/8WeYA4x+jsrZUHg4+YiV4XpPmTcRYn2aTq0oHE0 4MiNqsiT+67r5AT391KOvptk1P9UBofY= X-Gm-Gg: ASbGncsnQHy7iYGLQ+wkEf5FMshlFnKhNBjmDk0Rh1R79IBd6DiH9O44TvG0MjPYSAk 3OikVFeOvFnKcwI6CzhqWe9KdjO8dzPaCR5dgN4W0mL1AojCmJyHPVt7IcRxIt+LI+cDnlaKdCg wt7lyVUYbuyIFiDd2kpHPwd3om09/EIYm3J5thuOz50N1FBnz+xF7H6AwCoFQiQ7aQs++hXU0Q+ v/BlUgFJKRQqBIfJc90L6J+7W7jNgWnL5OcOZgHIVI6EZ5Lrm1n7DFGnMpV4NBoyOqKIkUOeFAO bvaKG81ahV4= X-Google-Smtp-Source: AGHT+IHJd2zmbH+2e7hDXL39V9Z2CpV2ucYugoqIdkeDnNNmGmNz7yqPsZCJPpTyoXdFPTG7UWOrx9YSsiI6sBP0xBs= X-Received: by 2002:a05:6512:108f:b0:594:49ed:3cf1 with SMTP id 2adb3069b0e04-597d3f02752mr1434276e87.10.1764791165680; Wed, 03 Dec 2025 11:46:05 -0800 (PST) MIME-Version: 1.0 References: <689686.1764787308@sss.pgh.pa.us> In-Reply-To: <689686.1764787308@sss.pgh.pa.us> From: Tim Fors Date: Wed, 3 Dec 2025 14:45:54 -0500 X-Gm-Features: AWmQ_blhWQrhMiPKj89PWqrGLFiK1fhjwmxj1Ptd6E4QEfmFw84UahUkAVsXsAk Message-ID: Subject: Re: Client-server communication for FETCH To: Tom Lane Cc: pgsql-performance@lists.postgresql.org Content-Type: multipart/alternative; boundary="000000000000887eed0645117646" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000887eed0645117646 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Thanks for the quick reply Tom. Let me give you a bit of background info: Oracle has a COBOL pre-processor for embedded SQL, and it supports an option named PREFETCH: The precompiler option PREFETCH allows for more efficient queries by > pre-fetching rows. This decreases the number of server round-trips needed > and reduces memory required. The number of rows set by the PREFETCH optio= n > value in a configuration file or on the command line is used for all > queries involving explicit cursors, subject to the standard precedence > rules. When used inline, the PREFETCH option must precede any of these > cursor statements: =E2=80=A2 EXEC SQL OPEN cursor =E2=80=A2 EXEC SQL OPEN= cursor USING > host_var_list =E2=80=A2 EXEC SQL OPEN cursor USING DESCRIPTOR desc_name W= hen an > OPEN is executed, the value of PREFETCH gives the number of rows to be > prefetched when the query is executed. You can set the value from 0 (no > pre-fetching) to 9999. The default value is 1. The IBM compiler for COBOL on Linux x86 recently added support for PGSQL (as a co-processor, integrated into the compiler). We have a business partner with a COBOL application that contains a large number of single-row FETCH statements, and they've noticed a significant performance degradation when switching from Oracle to PGSQL, and it's almost certainly because they're using that Oracle option PREFETCH. They are asserting that it's the large amount of client-server exchanges to retrieve one row at a time that is the problem in PGSQL. As you can imagine, they're not wanting to rework their application(s) in order to achieve the same performance - they want the single-row FETCH to be as performant as Oracle. And I'm sure this same stance would be adopted by other users of the compiler who want to use PGSQL as well. They have loops in their programs which FETCH rows one at a time. I was hoping that the "chunked mode" you mentioned would achieve the equivalent of a client-side cursor, but your answer indicates that it won't. The IBM co-processor is a rewrite of ECPG, and therefore uses libecpg at runtime, which of course uses libpq. Do you have any further thoughts re: addressing this requirement (client-side cursor support)? Is this a requirement that the PGSQL community would consider implementing in libpq? Without it, it seems like a huge impediment to adoption of PGSQL for COBOL applications, and as you probably know, COBOL applications are still very pervasive. (C programs using ECPG would of course hit the same issue, so it's not just a COBOL-specific problem.) Thanks, Tim On Wed, Dec 3, 2025 at 1:41=E2=80=AFPM Tom Lane wrote: > Tim Fors writes: > > I have a simple C program using libpq V18 to FETCH one row at a time (s= ee > > below). Does the server send multiple rows to the client where they are > > cached for satisfying the FETCH statements, or does it just send one ro= w > at > > a time since that's all that each FETCH statement is asking for? > > It's sending one row at a time. You could improve that by asking > for more than one row ("FETCH n" not just "FETCH"), but you'd have > to iterate over the rows returned by each command. > > Another alternative is to forget about using a cursor, tell the > server to just execute the query, but use libpq's "chunked results" > mode to process rows before all of the query result has arrived. > See > > https://www.postgresql.org/docs/current/libpq-single-row-mode.html > > > I have done extensive searching to try and find the definitive answer t= o > > this. The searches indicate that libpq supports the concept of a > > client-side cursor, where it has a cache of rows sent by the server and > > uses that cache to perform each FETCH, but I'd like to be able to verif= y > > whether this is true or not. > > Don't know where you read that, but it's not true of libpq. There > might be other Postgres client libraries that can do that. > > regards, tom lane > --000000000000887eed0645117646 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Thanks for the quick reply Tom.

Let me = give you a bit of background info:

Oracle has a CO= BOL pre-processor for embedded SQL, and it supports an option named PREFETC= H:=C2=A0=C2=A0

The precompiler option PREFETCH allows for more efficient querie= s by pre-fetching rows. This decreases the number of server round-trips needed and reduces memory requir= ed. The number of rows set by the PREFETCH option value in a configuration file or = on the command line is used for all queries involving explicit cursors, subject to the sta= ndard precedence rules. When used inline, the PREFETCH option must precede any of these cursor stat= ements: =E2=80=A2 EXEC SQL OPEN cursor =E2=80=A2 EXEC SQL OPEN cursor USING host_var_list =E2=80=A2 EXEC SQL OPEN cursor USING DESCRIPTOR desc_name When an OPEN is executed, the value of PREFETCH gives the number of rows to= be prefetched when the query is executed. You can set the value from 0 (no= pre-fetching) to 9999. The default value is 1.

The IBM compiler fo= r COBOL on Linux x86 recently added support for PGSQL (as a co-processor, i= ntegrated into the compiler). We have a business partner with a COBOL appli= cation that contains a large number of single-row FETCH statements, and the= y've noticed a significant performance degradation when switching from = Oracle to PGSQL, and it's almost certainly because they're using th= at Oracle option PREFETCH. They are asserting that it's the large amoun= t of client-server exchanges to retrieve one row at a time that is the prob= lem in PGSQL.

As you can imagine, they're not = wanting to rework their application(s) in order to achieve the same perform= ance - they want the single-row FETCH to be as performant as Oracle. And I&= #39;m sure this same stance would be adopted by other users of the compiler= who want to use PGSQL as well. They have loops in their programs which FET= CH rows one at a time.=C2=A0 I was hoping that the "chunked mode"= you mentioned would achieve the=C2=A0equivalent of a client-side cursor, b= ut your answer indicates that it won't.

The IB= M co-processor is a rewrite of ECPG, and therefore uses libecpg at runtime,= which of course uses libpq.

Do you have any furth= er thoughts re: addressing this requirement (client-side cursor support)? I= s this a requirement that the PGSQL community would consider implementing i= n libpq? Without it, it seems like a huge impediment to adoption of PGSQL f= or COBOL applications, and as you probably know, COBOL applications are sti= ll very pervasive. (C programs using ECPG would of course hit the same issu= e, so it's not just a COBOL-specific problem.)

Thanks,

Tim

On Wed, De= c 3, 2025 at 1:41=E2=80=AFPM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Tim Fors <tim4stheenchanter@gmail.com> writes:
> I have a simple C program using libpq V18 to FETCH one row at a time (= see
> below). Does the server send multiple rows to the client where they ar= e
> cached for satisfying the FETCH statements, or does it just send one r= ow at
> a time since that's all that each FETCH statement is asking for?
It's sending one row at a time.=C2=A0 You could improve that by asking<= br> for more than one row ("FETCH n" not just "FETCH"), but= you'd have
to iterate over the rows returned by each command.

Another alternative is to forget about using a cursor, tell the
server to just execute the query, but use libpq's "chunked results= "
mode to process rows before all of the query result has arrived.
See

https://www.postgresql.org/docs/cu= rrent/libpq-single-row-mode.html

> I have done extensive searching to try and find the definitive answer = to
> this. The searches indicate that libpq supports the concept of a
> client-side cursor, where it has a cache of rows sent by the server an= d
> uses that cache to perform each FETCH, but I'd like to be able to = verify
> whether this is true or not.

Don't know where you read that, but it's not true of libpq.=C2=A0 T= here
might be other Postgres client libraries that can do that.

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 regards, tom lane
--000000000000887eed0645117646--