Skip to content

Commit 96b0da4

Browse files
author
Evgeny Brednya
committed
Reinplementation for MR reorg#251
Use CREATE TABLE as SELECT allowing parallel plans if it is possible.
1 parent aae9f2f commit 96b0da4

2 files changed

Lines changed: 65 additions & 34 deletions

File tree

bin/pg_repack.c

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ static bool advisory_lock(PGconn *conn, const char *relid);
229229
static bool lock_exclusive(PGconn *conn, const char *relid, const char *lock_query, bool start_xact);
230230
static bool kill_ddl(PGconn *conn, Oid relid, bool terminate);
231231
static bool lock_access_share(PGconn *conn, Oid relid, const char *target_name);
232+
static void append_order_by_command(StringInfoData *command, const char *orderby, const char *ckey);
232233

233234
#define SQLSTATE_INVALID_SCHEMA_NAME "3F000"
234235
#define SQLSTATE_UNDEFINED_FUNCTION "42883"
@@ -787,7 +788,7 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
787788
/* acquire target tables */
788789
appendStringInfoString(&sql,
789790
"SELECT t.*,"
790-
" coalesce(v.tablespace, t.tablespace_orig) as tablespace_dest"
791+
" quote_ident(coalesce(v.tablespace, t.tablespace_orig)) as tablespace_dest"
791792
" FROM repack.tables t, "
792793
" (VALUES ($1::text)) as v (tablespace)"
793794
" WHERE ");
@@ -899,6 +900,7 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
899900
for (i = 0; i < num; i++)
900901
{
901902
repack_table table;
903+
StringInfoData create_sql;
902904
StringInfoData copy_sql;
903905
const char *ckey;
904906
int c = 0;
@@ -938,32 +940,37 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
938940
table.sql_pop = getstr(res, i, c++);
939941
table.dest_tablespace = getstr(res, i, c++);
940942

941-
/* Craft Copy SQL */
943+
/* Craft Create_Table and Copy SQLs */
944+
initStringInfo(&create_sql);
945+
printfStringInfo(&create_sql, table.create_table, table.dest_tablespace);
946+
947+
/*
948+
* We need to split the copying of data into the new table into
949+
* separate commands if we need any per-column storage settings.
950+
* Otherwise use just "create table as"
951+
*/
942952
initStringInfo(&copy_sql);
943-
appendStringInfoString(&copy_sql, table.copy_data);
944-
if (!orderby)
945953

954+
/* if columns are altered */
955+
if (table.alter_col_storage)
946956
{
947-
if (ckey != NULL)
948-
{
949-
/* CLUSTER mode */
950-
appendStringInfoString(&copy_sql, " ORDER BY ");
951-
appendStringInfoString(&copy_sql, ckey);
952-
}
957+
/* no data in CREATE TABLE */
958+
appendStringInfoString(&create_sql, " WITH NO DATA");
953959

954-
/* else, VACUUM FULL mode (non-clustered tables) */
955-
}
956-
else if (!orderby[0])
957-
{
958-
/* VACUUM FULL mode (for clustered tables too), do nothing */
959-
}
960-
else
961-
{
962-
/* User specified ORDER BY */
963-
appendStringInfoString(&copy_sql, " ORDER BY ");
964-
appendStringInfoString(&copy_sql, orderby);
960+
/* add ORDER BY in copy data */
961+
appendStringInfoString(&copy_sql, table.copy_data);
962+
append_order_by_command(&copy_sql, orderby, ckey);
963+
table.copy_data = copy_sql.data;
964+
965+
} else {
966+
967+
/* copy all data in CREATE TABLE AS with ORDER BY
968+
* allowing parallel SELECT executions */
969+
append_order_by_command(&create_sql, orderby, ckey);
970+
table.copy_data = NULL;
965971
}
966-
table.copy_data = copy_sql.data;
972+
973+
table.create_table = create_sql.data;
967974

968975
repack_one_table(&table, orderby);
969976
}
@@ -977,6 +984,33 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
977984
return ret;
978985
}
979986

987+
static void
988+
append_order_by_command(StringInfoData *command, const char *orderby, const char *ckey)
989+
{
990+
if (!orderby)
991+
992+
{
993+
if (ckey != NULL)
994+
{
995+
/* CLUSTER mode */
996+
appendStringInfoString(command, " ORDER BY ");
997+
appendStringInfoString(command, ckey);
998+
}
999+
1000+
/* else, VACUUM FULL mode (non-clustered tables) */
1001+
}
1002+
else if (!orderby[0])
1003+
{
1004+
/* VACUUM FULL mode (for clustered tables too), do nothing */
1005+
}
1006+
else
1007+
{
1008+
/* User specified ORDER BY */
1009+
appendStringInfoString(command, " ORDER BY ");
1010+
appendStringInfoString(command, orderby);
1011+
}
1012+
}
1013+
9801014
static int
9811015
apply_log(PGconn *conn, const repack_table *table, int count)
9821016
{
@@ -1524,12 +1558,11 @@ repack_one_table(repack_table *table, const char *orderby)
15241558
* Before copying data to the target table, we need to set the column storage
15251559
* type if its storage type has been changed from the type default.
15261560
*/
1527-
params[0] = utoa(table->target_oid, buffer);
1528-
params[1] = table->dest_tablespace;
1529-
command(table->create_table, 2, params);
1561+
command(table->create_table, 0, NULL);
15301562
if (table->alter_col_storage)
15311563
command(table->alter_col_storage, 0, NULL);
1532-
command(table->copy_data, 0, NULL);
1564+
if (table->copy_data)
1565+
command(table->copy_data, 0, NULL);
15331566
temp_obj_num++;
15341567
printfStringInfo(&sql, "SELECT repack.disable_autovacuum('repack.table_%u')", table->target_oid);
15351568
if (table->drop_columns)

lib/pg_repack.sql.in

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,15 @@ END
5959
$$
6060
LANGUAGE plpgsql;
6161

62-
CREATE FUNCTION repack.create_table(oid, name) RETURNS void AS
62+
CREATE FUNCTION repack.create_table(oid) RETURNS text AS
6363
$$
64-
BEGIN
65-
EXECUTE 'CREATE TABLE repack.table_' || $1 ||
64+
SELECT 'CREATE TABLE repack.table_' || $1 ||
6665
' WITH (' || repack.get_storage_param($1) || ') ' ||
67-
' TABLESPACE ' || quote_ident($2) ||
66+
' TABLESPACE %s' ||
6867
' AS SELECT ' || repack.get_columns_for_create_as($1) ||
69-
' FROM ONLY ' || repack.oid2text($1) || ' WITH NO DATA';
70-
END
68+
' FROM ONLY ' || repack.oid2text($1);
7169
$$
72-
LANGUAGE plpgsql;
70+
LANGUAGE sql STABLE STRICT;
7371

7472
CREATE FUNCTION repack.create_index_type(oid, oid) RETURNS void AS
7573
$$
@@ -299,7 +297,7 @@ CREATE VIEW repack.tables AS
299297
'SELECT repack.create_log_table(' || R.oid || ')' AS create_log,
300298
repack.get_create_trigger(R.oid, PK.indexrelid) AS create_trigger,
301299
repack.get_enable_trigger(R.oid) as enable_trigger,
302-
'SELECT repack.create_table($1, $2)'::text AS create_table,
300+
repack.create_table(R.oid)::text AS create_table,
303301
coalesce(S.spcname, S2.spcname) AS tablespace_orig,
304302
'INSERT INTO repack.table_' || R.oid || ' SELECT ' || repack.get_columns_for_create_as(R.oid) || ' FROM ONLY ' || repack.oid2text(R.oid) AS copy_data,
305303
repack.get_alter_col_storage(R.oid) AS alter_col_storage,

0 commit comments

Comments
 (0)