Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1i72ai-0003FO-B7 for pgsql-sql@arkaria.postgresql.org; Sun, 08 Sep 2019 19:11:16 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1i72Zi-0002IX-Qb for pgsql-sql@arkaria.postgresql.org; Sun, 08 Sep 2019 19:10:14 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1i72Zi-0002DS-Gi for pgsql-sql@lists.postgresql.org; Sun, 08 Sep 2019 19:10:14 +0000 Received: from mout.kundenserver.de ([217.72.192.74]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1i72Zf-000162-J3 for pgsql-sql@lists.postgresql.org; Sun, 08 Sep 2019 19:10:13 +0000 Received: from x230.onfire.org ([84.181.88.63]) by mrelayeu.kundenserver.de (mreue107 [212.227.15.183]) with ESMTPSA (Nemesis) id 1MkYsS-1iZGvA3Sko-00m640; Sun, 08 Sep 2019 21:10:06 +0200 From: Christian Barthel To: Sebastien FLAESCH Cc: pgsql-sql@lists.postgresql.org Subject: Re: libpq: How are result sets fetched behind the scene? In-Reply-To: <7e0c3606-1513-1120-555a-6a14b615d939@4js.com> (Sebastien FLAESCH's message of "Thu, 29 Aug 2019 18:39:13 +0200") Date: Sat, 07 Sep 2019 14:43:58 +0200 Message-ID: <87zhjg8eep.fsf@x230.onfire.org> References: <6f2f210b-53e6-f350-4850-83f49b2a1354@4js.com> <7e0c3606-1513-1120-555a-6a14b615d939@4js.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (berkeley-unix) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Provags-ID: V03:K1:MkpblS7iY1klJ4AKVQPn7dlkU/lfHNW5w6uOFqM7aLropqY6uIx G37bHoZR3Ku3LsSBPlcMUR6Pl4lmYnkqCHIm8Mx2SwyJIUAC3OfEZ0f3YI3+o1rdOhePFpG aUIf/KDf3M2COYFEVPLmdSlol0BSQraxz6915n5ZO1gD4OlxBHRDJUonw3uIAYKoS+GMI6i H24M2ghBMKPjr53HUKPfg== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:EeYO+EQWxdA=:OKuvdm1TXhDyydhrEnH6JO owRQwMbLpj0xggqqqkPba7msnN4k2XjtN0h165WRNoVDjmmEnqFeqcFHTMKx73w/1G6AxASt+ 9aUGNkwrSvcFmZZlduiWqyq9wkVq3spLRDsqzSHohTigSpLQWt9Q9zcMI9kneFPDW8FUz/Kz9 fT98MJFckGa6b2FWMRXo3F+65yFSQJWi7b9LMGEbZAC70KC6KLz4VMBEFDpthPTGuoTk2/Mfn TR0V7rUda9k52aX84V/Uel4oIQLZ8OrtM1SRIrquuHfaUtsmNyZ4HqKDI1n1FHeWbYpgubIpk z6sMiFCmYeXQAWAhrBuHf0JuthwXxYC877SPst8DoPDqTEpWh34qtM7mFC/ayHNBNNLKkRMg3 rWMhu4J5F8rhRLSSYSZ0CFBY7X9d4TSNy7CTU87AM91xjoBYXVrgo3zN0r/7+mL5TMfoSKKpG ZhFRZvt68BQnPRLQJ2Is90uioxymgBme4yN6z7+KWQd5UQsVQwdcHWlG4a6y1seXMmMCvAjSd Q3iH4yBvBabhhbhgSsSqHXS3cc2zw8cyGrhIEJsSOnAXLs5DWkKqKuHDWJgL3rbBgT0F/ftJF CSx0sHIbvBOZMY6zhLLla0QZbiwVOyLGdBalt6s5pJscVI3osMrzJk8Q8bIdf4OssvMLnfwUR xurIcMpAk8kShDQ3EpMwB+BIPysSvD3x4qjZVkQtfkAmlFZbnLzGSja5kX93Tx+d6Gxcz93V1 fFbjeOVrLTXnnJWvcjHoXB5Vjydd6Ys3kI9ORAHvIH5an9wJfzNDF4X6cyQt1Xq8rLcPdutRI f6AOb6n5Uu5u4nv4fB6d4WwCWuG+eMW1cG+kCzJz8j6NNJ24P0= List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --=-=-= Content-Type: text/plain Sebastien FLAESCH writes: > Is the whole result set fetched to the client app, not matter what row > number is provided to the first PQgetvalue() call (or similar API call > on result set data or meta-data)? I have tested this as well and came to the same result as you. The entire result set seems to be fetched at once. Attached is a test program: I have loaded 30MB of random strings and did a simple SELECT on the random data. I stopped the output with getchar() and looked at the network traffic and the memory usage with top(1). Everything gets allocated and fetched at once as far as I can see. However, I would not build an application that "depends" on this behavior. I think that it is better to use a declared cursor and use FETCH. -- Christian Barthel --=-=-= Content-Type: text/x-csrc Content-Disposition: attachment; filename=pg-fetchtest.c #include #include #include "libpq-fe.h" /* Source Code based on PostgreSQL/libpq Example Code */ /* begin; create table string_test (s char(32)); BEGIN CREATE TABLE insert into string_test(s) SELECT md5(random()::text) from generate_series(1,1000000); commit; */ static void exit_nicely(PGconn *conn) { PQfinish(conn); exit(1); } int main(int argc, char **argv) { const char *conninfo; PGconn *conn; PGresult *res; int nFields; int i, j; if (argc > 1) conninfo = argv[1]; else conninfo = "host=192.168.4.102 dbname=dbname"; conn = PQconnectdb(conninfo); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn)); exit_nicely(conn); } res = PQexec(conn, "SELECT pg_catalog.set_config('search_path', '', false)"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); res = PQexec(conn, "BEGIN"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); res = PQexec(conn, "select s from public.string_test"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "PQexec failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } nFields = PQnfields(res); for (i = 0; i < nFields; i++) printf("%-15s", PQfname(res, i)); printf("\n-----\n"); for (i = 0; i < PQntuples(res); i++) { for (j = 0; j < nFields; j++) printf("%-15s", PQgetvalue(res, i, j)); printf("\n"); getchar(); } PQclear(res); res = PQexec(conn, "ABORT"); PQclear(res); PQfinish(conn); return 0; } --=-=-=--