]> granicus.if.org Git - postgresql/commitdiff
In pg_upgrade, use cached copy of directory listing, rather than calling
authorBruce Momjian <bruce@momjian.us>
Wed, 20 Oct 2010 00:33:19 +0000 (00:33 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 20 Oct 2010 00:33:19 +0000 (00:33 +0000)
scandir() with a pattern for every table.

Optimization after report of pg_upgrade slowness with 150k tables.

contrib/pg_upgrade/info.c
contrib/pg_upgrade/pg_upgrade.h
contrib/pg_upgrade/relfilenode.c

index b4e414ec8d97874bfb44923c2b128d45ce050f1f..a8d0bddc1912e90fe7969900ad1073da64cadcdf 100644 (file)
@@ -30,8 +30,8 @@ static void map_rel_by_id(Oid oldid, Oid newid,
                          const char *old_tablespace, const DbInfo *old_db,
                          const DbInfo *new_db, const char *olddata,
                          const char *newdata, FileNameMap *map);
-static RelInfo *relarr_lookup_reloid(
-                                        RelInfoArr *rel_arr, Oid oid, Cluster whichCluster);
+static RelInfo *relarr_lookup_reloid(RelInfoArr *rel_arr,
+                               Oid oid, Cluster whichCluster);
 static RelInfo *relarr_lookup_rel(RelInfoArr *rel_arr,
                                  const char *nspname, const char *relname,
                                  Cluster whichCluster);
@@ -172,8 +172,8 @@ map_rel_by_id(Oid oldid, Oid newid,
                 * relation belongs to the default tablespace, hence relfiles would
                 * exist in the data directories.
                 */
-               snprintf(map->old_file, sizeof(map->old_file), "%s/base/%u", olddata, old_db->db_oid);
-               snprintf(map->new_file, sizeof(map->new_file), "%s/base/%u", newdata, new_db->db_oid);
+               snprintf(map->old_dir, sizeof(map->old_dir), "%s/base/%u", olddata, old_db->db_oid);
+               snprintf(map->new_dir, sizeof(map->new_dir), "%s/base/%u", newdata, new_db->db_oid);
        }
        else
        {
@@ -181,9 +181,9 @@ map_rel_by_id(Oid oldid, Oid newid,
                 * relation belongs to some tablespace, hence copy its physical
                 * location
                 */
-               snprintf(map->old_file, sizeof(map->old_file), "%s%s/%u", old_tablespace,
+               snprintf(map->old_dir, sizeof(map->old_dir), "%s%s/%u", old_tablespace,
                                 old_cluster.tablespace_suffix, old_db->db_oid);
-               snprintf(map->new_file, sizeof(map->new_file), "%s%s/%u", old_tablespace,
+               snprintf(map->new_dir, sizeof(map->new_dir), "%s%s/%u", old_tablespace,
                                 new_cluster.tablespace_suffix, new_db->db_oid);
        }
 }
@@ -318,6 +318,7 @@ get_rel_infos(const DbInfo *dbinfo,
         * pg_largeobject_loid_pn_index's relfilenode can change if the table was
         * reindexed so we get the relfilenode for each database and migrate it as
         * a normal user table.
+        * Order by tablespace so we can cache the directory contents efficiently.
         */
 
        snprintf(query, sizeof(query),
@@ -338,7 +339,7 @@ get_rel_infos(const DbInfo *dbinfo,
                         "GROUP BY  c.oid, n.nspname, c.relname, c.relfilenode,"
                         "                      c.reltoastrelid, t.spclocation, "
                         "                      n.nspname "
-                        "ORDER BY n.nspname, c.relname;",
+                        "ORDER BY t.spclocation, n.nspname, c.relname;",
                         FirstNormalObjectId,
        /* see the comment at the top of old_8_3_create_sequence_script() */
                         (GET_MAJOR_VERSION(old_cluster.major_version) <= 803) ?
index 3756f5cbb0a4f410a651ee0b3052fa491a2e724f..2aa220815820fa3921599230a412dd666402a6c6 100644 (file)
@@ -85,10 +85,10 @@ typedef struct
  */
 typedef struct
 {
+       char            old_dir[MAXPGPATH];
+       char            new_dir[MAXPGPATH];
        Oid                     old_relfilenode;        /* Relfilenode of the old relation */
        Oid                     new_relfilenode;        /* Relfilenode of the new relation */
-       char            old_file[MAXPGPATH];
-       char            new_file[MAXPGPATH];
        char            old_nspname[NAMEDATALEN];               /* old name of the namespace */
        char            old_relname[NAMEDATALEN];               /* old name of the relation */
        char            new_nspname[NAMEDATALEN];               /* new name of the namespace */
@@ -255,10 +255,8 @@ void check_old_cluster(bool live_check,
                                  char **sequence_script_file_name);
 void           check_new_cluster(void);
 void           report_clusters_compatible(void);
-void issue_warnings(
-                          char *sequence_script_file_name);
-void output_completion_banner(
-                                                char *deletion_script_file_name);
+void issue_warnings(char *sequence_script_file_name);
+void output_completion_banner(char *deletion_script_file_name);
 void           check_cluster_versions(void);
 void           check_cluster_compatibility(bool live_check);
 void           create_script_for_old_cluster_deletion(char **deletion_script_file_name);
@@ -319,14 +317,12 @@ typedef void *pageCnvCtx;
 #endif
 
 int                    dir_matching_filenames(const struct dirent * scan_ent);
-int pg_scandir(const char *dirname,
-                  struct dirent *** namelist,
-                  int (*selector) (const struct dirent *));
-const char *copyAndUpdateFile(
-                                 pageCnvCtx *pageConverter, const char *src,
+int pg_scandir(const char *dirname, struct dirent *** namelist,
+                          int (*selector) (const struct dirent *));
+const char *copyAndUpdateFile(pageCnvCtx *pageConverter, const char *src,
                                  const char *dst, bool force);
-const char *linkAndUpdateFile(
-                               pageCnvCtx *pageConverter, const char *src, const char *dst);
+const char *linkAndUpdateFile(pageCnvCtx *pageConverter, const char *src,
+                                                         const char *dst);
 
 void           check_hard_link(void);
 
@@ -374,8 +370,7 @@ PGresult *executeQueryOrDie(PGconn *conn,
 
 void           start_postmaster(Cluster whichCluster, bool quiet);
 void           stop_postmaster(bool fast, bool quiet);
-uint32 get_major_server_version(char **verstr,
-                                                Cluster whichCluster);
+uint32 get_major_server_version(char **verstr, Cluster whichCluster);
 void           check_for_libpq_envvars(void);
 
 
index ff1a73cdec2c18dab0084b9b064a13531068408c..7b73b5e91f5603d4a83b130adcd6458cb2efd1d7 100644 (file)
@@ -110,20 +110,38 @@ static void
 transfer_single_new_db(pageCnvCtx *pageConverter,
                                           FileNameMap *maps, int size)
 {
+       char            old_dir[MAXPGPATH];
+       struct dirent **namelist = NULL;
+       int                     numFiles = 0;
        int                     mapnum;
+       int                     fileno;
+
+       old_dir[0] = '\0';
 
        for (mapnum = 0; mapnum < size; mapnum++)
        {
                char            old_file[MAXPGPATH];
                char            new_file[MAXPGPATH];
-               struct dirent **namelist = NULL;
-               int                     numFiles;
+
+               /* Changed tablespaces?  Need a new directory scan? */
+               if (strcmp(maps[mapnum].old_dir, old_dir) != 0)
+               {
+                       if (numFiles > 0)
+                       {
+                               for (fileno = 0; fileno < numFiles; fileno++)
+                                       pg_free(namelist[fileno]);
+                               pg_free(namelist);
+                       }
+
+                       snprintf(old_dir, sizeof(old_dir), "%s", maps[mapnum].old_dir);
+                       numFiles = pg_scandir(old_dir, &namelist, NULL);
+               }
 
                /* Copying files might take some time, so give feedback. */
 
-               snprintf(old_file, sizeof(old_file), "%s/%u", maps[mapnum].old_file,
+               snprintf(old_file, sizeof(old_file), "%s/%u", maps[mapnum].old_dir,
                                 maps[mapnum].old_relfilenode);
-               snprintf(new_file, sizeof(new_file), "%s/%u", maps[mapnum].new_file,
+               snprintf(new_file, sizeof(new_file), "%s/%u", maps[mapnum].new_dir,
                                 maps[mapnum].new_relfilenode);
                pg_log(PG_REPORT, OVERWRITE_MESSAGE, old_file);
 
@@ -139,28 +157,27 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
                if (GET_MAJOR_VERSION(old_cluster.major_version) >= 804)
                {
                        /*
-                        * Now copy/link any fsm and vm files, if they exist
+                        * Copy/link any fsm and vm files, if they exist
                         */
                        snprintf(scandir_file_pattern, sizeof(scandir_file_pattern), "%u_",
                                         maps[mapnum].old_relfilenode);
-                       numFiles = pg_scandir(maps[mapnum].old_file, &namelist, dir_matching_filenames);
 
-                       while (numFiles--)
+                       for (fileno = 0; fileno < numFiles; fileno++)
                        {
-                               snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_file,
-                                                namelist[numFiles]->d_name);
-                               snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_file,
-                                                maps[mapnum].new_relfilenode, strchr(namelist[numFiles]->d_name, '_'));
-
-                               unlink(new_file);
-                               transfer_relfile(pageConverter, old_file, new_file,
-                                                 maps[mapnum].old_nspname, maps[mapnum].old_relname,
-                                                maps[mapnum].new_nspname, maps[mapnum].new_relname);
-
-                               pg_free(namelist[numFiles]);
+                               if (strncmp(namelist[fileno]->d_name, scandir_file_pattern,
+                                       strlen(scandir_file_pattern)) == 0)
+                               {
+                                       snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_dir,
+                                                        namelist[fileno]->d_name);
+                                       snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_dir,
+                                                        maps[mapnum].new_relfilenode, strchr(namelist[fileno]->d_name, '_'));
+       
+                                       unlink(new_file);
+                                       transfer_relfile(pageConverter, old_file, new_file,
+                                                         maps[mapnum].old_nspname, maps[mapnum].old_relname,
+                                                        maps[mapnum].new_nspname, maps[mapnum].new_relname);
+                               }
                        }
-
-                       pg_free(namelist);
                }
 
                /*
@@ -172,23 +189,30 @@ transfer_single_new_db(pageCnvCtx *pageConverter,
                 */
                snprintf(scandir_file_pattern, sizeof(scandir_file_pattern), "%u.",
                                 maps[mapnum].old_relfilenode);
-               numFiles = pg_scandir(maps[mapnum].old_file, &namelist, dir_matching_filenames);
 
-               while (numFiles--)
+               for (fileno = 0; fileno < numFiles; fileno++)
                {
-                       snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_file,
-                                        namelist[numFiles]->d_name);
-                       snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_file,
-                                        maps[mapnum].new_relfilenode, strchr(namelist[numFiles]->d_name, '.'));
-
-                       unlink(new_file);
-                       transfer_relfile(pageConverter, old_file, new_file,
-                                                 maps[mapnum].old_nspname, maps[mapnum].old_relname,
-                                                maps[mapnum].new_nspname, maps[mapnum].new_relname);
+                       if (strncmp(namelist[fileno]->d_name, scandir_file_pattern,
+                               strlen(scandir_file_pattern)) == 0)
+                       {
+                               snprintf(old_file, sizeof(old_file), "%s/%s", maps[mapnum].old_dir,
+                                                namelist[fileno]->d_name);
+                               snprintf(new_file, sizeof(new_file), "%s/%u%s", maps[mapnum].new_dir,
+                                                maps[mapnum].new_relfilenode, strchr(namelist[fileno]->d_name, '.'));
 
-                       pg_free(namelist[numFiles]);
+                               unlink(new_file);
+                               transfer_relfile(pageConverter, old_file, new_file,
+                                                         maps[mapnum].old_nspname, maps[mapnum].old_relname,
+                                                        maps[mapnum].new_nspname, maps[mapnum].new_relname);
+                       }
                }
+       }
 
+
+       if (numFiles > 0)
+       {
+               for (fileno = 0; fileno < numFiles; fileno++)
+                       pg_free(namelist[fileno]);
                pg_free(namelist);
        }
 }