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 1uZz2G-00CCnO-4t for pgsql-hackers@arkaria.postgresql.org; Thu, 10 Jul 2025 21:42:32 +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 1uZz2E-00HNdK-5h for pgsql-hackers@arkaria.postgresql.org; Thu, 10 Jul 2025 21:42:30 +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.94.2) (envelope-from ) id 1uZz2D-00HNdC-Qy for pgsql-hackers@lists.postgresql.org; Thu, 10 Jul 2025 21:42:30 +0000 Received: from mail-il1-x136.google.com ([2607:f8b0:4864:20::136]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uZz2B-006uVj-3A for pgsql-hackers@lists.postgresql.org; Thu, 10 Jul 2025 21:42:30 +0000 Received: by mail-il1-x136.google.com with SMTP id e9e14a558f8ab-3dc9e7d10bdso4765445ab.2 for ; Thu, 10 Jul 2025 14:42:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752183745; x=1752788545; darn=lists.postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=aycwP0tNp8sRpei6eT6p3oqZgSb6HY7YsJAy9NZOXkk=; b=Dgig40LQ8QDUgMRpx5wStJqa0eiH+jRZXXBVnMxeHQEyQGK+alLDOWAb+mbigRRJLI hJb8wA63z/U6t8vxpyHRK5rLLm4mBKv0ZrXW32617HqMFAnZN/ZS1DCLtYQ3E/nbahUT SGn3ONJlizh/I60HVzrLpC64B4dyejb5BWIuAEmhtJjrO9kUwsvtYaXqdo+BKZMysBqJ 77F1IzQ4sOFu11KNUHBpH5x7EDGw7oL589fkwwaOl0BKV4bo8S6qlGuLzk+MCW2iTgv1 0hZMV3nudlKp22NXDmti0avoyhAM9KDxVSjhf3yVzKhnYhXI9pmREZSZ+DOIf7e53ogm 3RNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752183745; x=1752788545; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=aycwP0tNp8sRpei6eT6p3oqZgSb6HY7YsJAy9NZOXkk=; b=j9umT6dDFOtqVqXaELQuQDj2n9iqF7mCvCVQb9lKeNAJaPSy0//n0wJgdUk5OZ7x3s Uvu9c18CvU/BsGiljax680+AXf156ENCWrGuzndcXJNnRSavE7I3KdDKg5whpXA24Baw n2W+YsNi3aD2s/0fCN6t7i8VisQtMqcRXSs7ohhDL+U+XONNOtk+W/zAcXR4tbQEHr47 fvmI+z9PDnf1nBA+d+3gP4VbTXLTstgBbYjQLcilRSr5XINQCuqrhTSSRSZHR5VQlGJ7 u+FeQx4+ZKkbOwpLOQZl/m4njh4zpRnw+WPjzooQjJZG5ncZQBP16czBwC5OFmScpgrN CP/A== X-Forwarded-Encrypted: i=1; AJvYcCVDreth7wW1PWbll6BgcWdIitVHKtsVTL0NTX3KidF0NgyoE5I+Bf4uunGxbpZV4q98yGRoigujuJaEjQZX@lists.postgresql.org X-Gm-Message-State: AOJu0YyefY1kHCV5vHuZ5u5rPlUcv+zv5PLjlMV/S62gJzqIhxvvQori /+CfBQyR0z5ABeRpnZ8+b5fK0t58yc/dU6pv/OC2huxT5aMVLlzFBPTU X-Gm-Gg: ASbGncuhT1xJA3zKo3r5pn8Eb+N4c750jEsH54KMXcht8nD76bmGjQF2CkBODBSv+Ub gv8gqpxJFmVJcZyPySz1mgGPJu2YAYZ3TkKYmpWdBJv+YRvDHEAeQKnsvLoiOySMww1mFPU3Ez2 ug7tEEt7YM3vYFCHMLbvwph+rZCDsHw/aYVjoK9fwtsXDDmtC/FB8r8fAOPO8XRoq9LUxSXb8l6 fnk4WvOoLEqd83k/PtgK+WX1bNiVUMRM9QnAVndJF/Zzk2DxjW/jB+4D1u8eixKIRcGMHb7QPPz niE/yK9fQBleWoyMTKr7NXsvCrVLQ7tFVbHgCJZnyhqrxPZRWMT4M5BRgPPpdZGxVBM1bOKa6kX LkmqbmDM+DrOY4kRExBkh/z0zFe8bELUSBMVCFPuuxiAXasuNM4sM X-Google-Smtp-Source: AGHT+IFWXy65fijwi+ivjj9SHztW7CPIiTFlyZaT92Djpuqgk7iZeXRWoJP2/mXq/+w4x/4AeNyKVw== X-Received: by 2002:a05:6e02:2403:b0:3df:5354:a804 with SMTP id e9e14a558f8ab-3e25332a066mr17100275ab.18.1752183745494; Thu, 10 Jul 2025 14:42:25 -0700 (PDT) Received: from nathan (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-3e246135327sm7646795ab.23.2025.07.10.14.42.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Jul 2025 14:42:24 -0700 (PDT) Date: Thu, 10 Jul 2025 16:42:23 -0500 From: Nathan Bossart To: Nitin Motiani Cc: Hannu Krosing , Tom Lane , PostgreSQL Hackers Subject: Re: Horribly slow pg_upgrade performance with many Large Objects Message-ID: References: <4050387.1744132029@sss.pgh.pa.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="wDo6IHo3pIZ/EZgg" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --wDo6IHo3pIZ/EZgg Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Thu, Jul 10, 2025 at 06:05:26PM +0530, Nitin Motiani wrote: > - * pg_largeobject_metadata, after the dump is restored. > + * pg_largeobject_metadata, after the dump is restored. In versions > + * before v12, this is done via proper large object commands. In > + * newer versions, we dump the content of pg_largeobject_metadata and > + * any associated pg_shdepend rows, which is faster to restore. > */ > > Should the comment provide further detail on why this is only being done > for v12 and above? Yes. I've fixed this in v3. -- nathan --wDo6IHo3pIZ/EZgg Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0001-pg_upgrade-Use-COPY-for-large-object-metadata.patch From b784cd881933a1c01f4ea143f06bf77972924459 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 10 Jul 2025 16:20:33 -0500 Subject: [PATCH v3 1/1] pg_upgrade: Use COPY for large object metadata. Reported-by: Hannu Krosing Suggested-by: Tom Lane Reviewed-by: Hannu Krosing Reviewed-by: Nitin Motiani Discussion: https://postgr.es/m/CAMT0RQSS-6qLH%2BzYsOeUbAYhop3wmQTkNmQpo5--QRDUR%2BqYmQ%40mail.gmail.com --- src/bin/pg_dump/pg_backup_archiver.c | 15 +++++ src/bin/pg_dump/pg_dump.c | 84 ++++++++++++++++++++++++++-- src/bin/pg_dump/t/002_pg_dump.pl | 4 +- 3 files changed, 97 insertions(+), 6 deletions(-) diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 197c1295d93..1b1c61e5ce5 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -31,6 +31,8 @@ #endif #include "catalog/pg_class_d.h" +#include "catalog/pg_largeobject_metadata.h" +#include "catalog/pg_shdepend.h" #include "common/string.h" #include "compress_io.h" #include "dumputils.h" @@ -2974,6 +2976,19 @@ _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH) int res = REQ_SCHEMA | REQ_DATA; RestoreOptions *ropt = AH->public.ropt; + /* + * For binary upgrade mode, dump pg_largeobject_metadata and the + * associated pg_shdepend rows. This is faster to restore than the + * equivalent set of large object commands. We can only do this for + * upgrades from v12 and newer; in older versions, pg_largeobject_metadata + * was created WITH OIDS, so the OID column is hidden and won't be dumped. + */ + if (ropt->binary_upgrade && AH->public.remoteVersion >= 120000 && + strcmp(te->desc, "TABLE DATA") == 0 && + (te->catalogId.oid == LargeObjectMetadataRelationId || + te->catalogId.oid == SharedDependRelationId)) + return REQ_DATA; + /* These items are treated specially */ if (strcmp(te->desc, "ENCODING") == 0 || strcmp(te->desc, "STDSTRINGS") == 0 || diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 1937997ea67..bdea0ef7c50 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -49,8 +49,10 @@ #include "catalog/pg_class_d.h" #include "catalog/pg_default_acl_d.h" #include "catalog/pg_largeobject_d.h" +#include "catalog/pg_largeobject_metadata_d.h" #include "catalog/pg_proc_d.h" #include "catalog/pg_publication_d.h" +#include "catalog/pg_shdepend.h" #include "catalog/pg_subscription_d.h" #include "catalog/pg_type_d.h" #include "common/connect.h" @@ -209,6 +211,12 @@ static int nbinaryUpgradeClassOids = 0; static SequenceItem *sequences = NULL; static int nsequences = 0; +/* + * For binary upgrade, the dump ID of pg_largeobject_metadata is saved for use + * as a dependency for pg_shdepend and any large object comments/seclabels. + */ +static DumpId lo_metadata_dumpId; + /* Maximum number of relations to fetch in a fetchAttributeStats() call. */ #define MAX_ATTR_STATS_RELS 64 @@ -1085,6 +1093,36 @@ main(int argc, char **argv) if (!dopt.dumpData && dopt.sequence_data) getTableData(&dopt, tblinfo, numTables, RELKIND_SEQUENCE); + /* + * For binary upgrade mode, dump pg_largeobject_metadata and the + * associated pg_shdepend rows. This is faster to restore than the + * equivalent set of large object commands. We can only do this for + * upgrades from v12 and newer; in older versions, pg_largeobject_metadata + * was created WITH OIDS, so the OID column is hidden and won't be dumped. + */ + if (dopt.binary_upgrade && fout->remoteVersion >= 120000) + { + TableInfo *lo_metadata = findTableByOid(LargeObjectMetadataRelationId); + TableInfo *shdepend = findTableByOid(SharedDependRelationId); + + makeTableDataInfo(&dopt, lo_metadata); + makeTableDataInfo(&dopt, shdepend); + + /* + * Save pg_largeobject_metadata's dump ID for use as a dependency on + * pg_shdepend and any large object comments/seclabels. + */ + lo_metadata_dumpId = lo_metadata->dataObj->dobj.dumpId; + addObjectDependency(&shdepend->dataObj->dobj, lo_metadata_dumpId); + + /* + * Only dump large object shdepend rows for this database. + */ + shdepend->dataObj->filtercond = "WHERE classid = 'pg_largeobject'::regclass " + "AND dbid = (SELECT oid FROM pg_database " + " WHERE datname = current_database())"; + } + /* * In binary-upgrade mode, we do not have to worry about the actual LO * data or the associated metadata that resides in the pg_largeobject and @@ -3924,10 +3962,31 @@ getLOs(Archive *fout) * as it will be copied by pg_upgrade, which simply copies the * pg_largeobject table. We *do* however dump out anything but the * data, as pg_upgrade copies just pg_largeobject, but not - * pg_largeobject_metadata, after the dump is restored. + * pg_largeobject_metadata, after the dump is restored. In versions + * before v12, this is done via proper large object commands. In + * newer versions, we dump the content of pg_largeobject_metadata and + * any associated pg_shdepend rows, which is faster to restore. (On + *