[PATCH] vacuumlo: print the number of large objects going to be removed

2019-06-12 Thread Timur Birsh
Hello,

If tables has a lot of rows with large objects (>1_000_000) that
removed throughout the day, it would be useful to know how many
LOs going to be removed.

First patch - print the number of large objects going to be removed,
second patch - print how many LOs removed in percent.

Can anyone please review.

Please cc, I am not subscribed to the list.

Regards,
TimurFrom 8465774c33b200c1a531465acaef85d2d261bb26 Mon Sep 17 00:00:00 2001
From: Timur Birsh 
Date: Wed, 12 Jun 2019 04:13:29 +
Subject: [PATCH 1/2] vacuumlo: print the number of large objects going to be
 removed

If tables has a lot of rows with large objects (>1_000_000) that
removed throughout the day, it would be useful to know how many
LOs going to be removed.
---
 contrib/vacuumlo/vacuumlo.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/contrib/vacuumlo/vacuumlo.c b/contrib/vacuumlo/vacuumlo.c
index 73c06a043e..beade1c9c0 100644
--- a/contrib/vacuumlo/vacuumlo.c
+++ b/contrib/vacuumlo/vacuumlo.c
@@ -64,6 +64,7 @@ vacuumlo(const char *database, const struct _param *param)
 	PGresult   *res,
 			   *res2;
 	char		buf[BUFSIZE];
+	long		to_delete = 0;
 	long		matched;
 	long		deleted;
 	int			i;
@@ -276,6 +277,25 @@ vacuumlo(const char *database, const struct _param *param)
 	}
 	PQclear(res);
 
+	if (param->verbose)
+	{
+		snprintf(buf, BUFSIZE, "SELECT count(*) FROM vacuum_l");
+		res = PQexec(conn, buf);
+		if (PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			fprintf(stderr, "Failed to get number of large objects "
+	"going to be removed:\n");
+			fprintf(stderr, "%s", PQerrorMessage(conn));
+			PQclear(res);
+			PQfinish(conn);
+			return -1;
+		}
+		to_delete = strtol(PQgetvalue(res, 0, 0), NULL, 10);
+		PQclear(res);
+		fprintf(stdout, "%ld large objects will be removed\n",
+to_delete);
+	}
+
 	/*
 	 * Now, those entries remaining in vacuum_l are orphans.  Delete 'em.
 	 *
-- 
2.17.1

From 4be55b5b5e566faad441824910b4e49c6b5f5879 Mon Sep 17 00:00:00 2001
From: Timur Birsh 
Date: Wed, 12 Jun 2019 05:56:44 +
Subject: [PATCH 2/2] vacuumlo: print how many LOs removed in percent

---
 contrib/vacuumlo/vacuumlo.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/contrib/vacuumlo/vacuumlo.c b/contrib/vacuumlo/vacuumlo.c
index beade1c9c0..5d629264f1 100644
--- a/contrib/vacuumlo/vacuumlo.c
+++ b/contrib/vacuumlo/vacuumlo.c
@@ -359,7 +359,8 @@ vacuumlo(const char *database, const struct _param *param)
 
 			if (param->verbose)
 			{
-fprintf(stdout, "\rRemoving lo %6u   ", lo);
+fprintf(stdout, "\rRemoving lo %6u\t(%3.f%%)", lo,
+		((float) deleted / (float) to_delete) * 100);
 fflush(stdout);
 			}
 
-- 
2.17.1



Re: [PATCH] vacuumlo: print the number of large objects going to be removed

2019-06-12 Thread Timur Birsh
12.06.2019, 14:31, "Timur Birsh" :
> Please cc, I am not subscribed to the list.

I have subscribed to the mailing list, there is no need to cc me.

Thank you.




Re: [PATCH] vacuumlo: print the number of large objects going to be removed

2019-06-13 Thread Timur Birsh
Hello Michael,

13.06.2019, 12:11, "Michael Paquier" :
> Welcome. Nice to see that you have subscribed to the lists.

Thank you for your explanations!

> Now, if you want to get review for your patch, you should register it
> in what we call the commit fest app, which is here:
> https://commitfest.postgresql.org/23/

Done. Please see https://commitfest.postgresql.org/23/2148/

> Commit fests happen every two months for a duration of one month, and
> the next one which will begin the development cycle of v13 begins on
> the 1st of July. As a basic rule, it is expected that for one patch
> submitted, you should review another patch of equal difficulty to keep
> some balance in the force.

Ok.

> Regarding the patch, there is an argument to be made for reporting a
> rate as well as the actual numbers of deleted and to-delete items.
>
> + if (param->verbose)
> + {
> + snprintf(buf, BUFSIZE, "SELECT count(*) FROM vacuum_l");
> + res = PQexec(conn, buf);
> That part is costly.

Just to be sure, a new command line argument needs to be added for
reporting the numbers? Should it implies --verbose argument?

Thanks,
Timur




Re: [PATCH] vacuumlo: print the number of large objects going to be removed

2019-06-13 Thread Timur Birsh
13.06.2019, 13:57, "Michael Paquier" :
> On Thu, Jun 13, 2019 at 01:25:38PM +0600, Timur Birsh wrote:
>>  Just to be sure, a new command line argument needs to be added for
>>  reporting the numbers? Should it implies --verbose argument?
>
> Nope. I mean that running a SELECT count(*) can be costly for many
> items.

Understood, thanks.

I found a way to get the number of LOs that will be removed without
the SELECT count(*) - PQcmdTuples(). Please find attached patch v2.
I fixed some indentation in the variable declaration blocks.

There is a database with tables that have a lot of tuples with large objects:

# select count(*) from pg_largeobject_metadata;
  count
--
 44707424
(1 row)

An application that uses this database from time to time deletes and adds a lot
of rows, it happens that more than 10,000,000 orphaned LOs remain in the
database. Removing such a number of items takes a long time.
I guess, it would be helpful to know how many LOs going to be removed and
report deleted percentage.

Thanks,
TimurFrom 2350a42ec46ab511020060b3f4427848628b0ecb Mon Sep 17 00:00:00 2001
From: Timur Birsh 
Date: Fri, 14 Jun 2019 04:31:28 +
Subject: [PATCH] Report the number of large objects going to be removed

---
 contrib/vacuumlo/vacuumlo.c | 29 +++--
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/contrib/vacuumlo/vacuumlo.c b/contrib/vacuumlo/vacuumlo.c
index 73c06a043e..77e91ff7ad 100644
--- a/contrib/vacuumlo/vacuumlo.c
+++ b/contrib/vacuumlo/vacuumlo.c
@@ -60,17 +60,18 @@ static void usage(const char *progname);
 static int
 vacuumlo(const char *database, const struct _param *param)
 {
-	PGconn	   *conn;
-	PGresult   *res,
-			   *res2;
+	PGconn		*conn;
+	PGresult	*res,
+			*res2;
 	char		buf[BUFSIZE];
+	long		to_delete = 0;
 	long		matched;
 	long		deleted;
-	int			i;
+	int		i;
 	bool		new_pass;
 	bool		success = true;
-	static bool have_password = false;
-	static char password[100];
+	static bool	have_password = false;
+	static char	password[100];
 
 	/* Note: password can be carried over from a previous call */
 	if (param->pg_prompt == TRI_YES && !have_password)
@@ -171,6 +172,7 @@ vacuumlo(const char *database, const struct _param *param)
 		PQfinish(conn);
 		return -1;
 	}
+	to_delete = strtol(PQcmdTuples(res), NULL, 10);
 	PQclear(res);
 
 	/*
@@ -221,9 +223,10 @@ vacuumlo(const char *database, const struct _param *param)
 
 	for (i = 0; i < PQntuples(res); i++)
 	{
-		char	   *schema,
-   *table,
-   *field;
+		char	*schema,
+			*table,
+			*field;
+		long	excluded;
 
 		schema = PQgetvalue(res, i, 0);
 		table = PQgetvalue(res, i, 1);
@@ -268,7 +271,9 @@ vacuumlo(const char *database, const struct _param *param)
 			PQfreemem(field);
 			return -1;
 		}
+		excluded = strtol(PQcmdTuples(res2), NULL, 10);
 		PQclear(res2);
+		to_delete -= excluded;
 
 		PQfreemem(schema);
 		PQfreemem(table);
@@ -276,6 +281,9 @@ vacuumlo(const char *database, const struct _param *param)
 	}
 	PQclear(res);
 
+	if (param->verbose)
+		fprintf(stdout, "%ld large objects will be removed\n", to_delete);
+
 	/*
 	 * Now, those entries remaining in vacuum_l are orphans.  Delete 'em.
 	 *
@@ -339,7 +347,8 @@ vacuumlo(const char *database, const struct _param *param)
 
 			if (param->verbose)
 			{
-fprintf(stdout, "\rRemoving lo %6u   ", lo);
+fprintf(stdout, "\rRemoving lo %6u\t(%3.f%%)", lo,
+		((float) deleted / (float) to_delete) * 100);
 fflush(stdout);
 			}
 
-- 
2.17.1