From 3119009acfebd4e7bff4110485a9f2c1d81e09a7 Mon Sep 17 00:00:00 2001 From: Ning Yu Date: Thu, 22 Nov 2018 10:30:21 +0800 Subject: [PATCH] New extension to debug partially distributed tables Introduced a new debugging extension gp_debug_numsegments to get / set the default numsegments when creating tables. gp_debug_get_create_table_default_numsegments() gets the default numsegments. gp_debug_set_create_table_default_numsegments(text) sets the default numsegments in text format, valid values are: - 'FULL': all the segments; - 'RANDOM': pick a random set of segments each time; - 'MINIMAL': the minimal set of segments; gp_debug_set_create_table_default_numsegments(integer) sets the default numsegments directly, valid range is [1, gp_num_contents_in_cluster]. gp_debug_reset_create_table_default_numsegments(text) or gp_debug_reset_create_table_default_numsegments(integer) reset the default numsegments to the specified value, and the value can be reused later. gp_debug_reset_create_table_default_numsegments() resets the default numsegments to the value passed last time, if there is no previous call to it the value is 'FULL'. Refactored ICG test partial_table.sql to create partial tables with this extension. --- gpcontrib/Makefile | 1 + gpcontrib/gp_debug_numsegments/Makefile | 19 ++ gpcontrib/gp_debug_numsegments/README.md | 41 ++++ .../expected/default_numsegments.out | 188 +++++++++++++++++ .../expected/reset_numsegments.out | 190 ++++++++++++++++++ .../gp_debug_numsegments--1.0.sql | 38 ++++ .../gp_debug_numsegments.c | 162 +++++++++++++++ .../gp_debug_numsegments.control | 5 + .../sql/default_numsegments.sql | 86 ++++++++ .../sql/reset_numsegments.sql | 85 ++++++++ src/backend/cdb/cdbcat.c | 15 ++ src/backend/cdb/cdbmutate.c | 7 +- src/backend/parser/analyze.c | 2 +- src/backend/parser/parse_utilcmd.c | 12 +- src/include/catalog/gp_policy.h | 41 ++++ src/test/regress/expected/partial_table.out | 68 +++++-- src/test/regress/greenplum_schedule | 5 +- src/test/regress/sql/partial_table.sql | 47 +++-- 18 files changed, 961 insertions(+), 51 deletions(-) create mode 100644 gpcontrib/gp_debug_numsegments/Makefile create mode 100644 gpcontrib/gp_debug_numsegments/README.md create mode 100644 gpcontrib/gp_debug_numsegments/expected/default_numsegments.out create mode 100644 gpcontrib/gp_debug_numsegments/expected/reset_numsegments.out create mode 100644 gpcontrib/gp_debug_numsegments/gp_debug_numsegments--1.0.sql create mode 100644 gpcontrib/gp_debug_numsegments/gp_debug_numsegments.c create mode 100644 gpcontrib/gp_debug_numsegments/gp_debug_numsegments.control create mode 100644 gpcontrib/gp_debug_numsegments/sql/default_numsegments.sql create mode 100644 gpcontrib/gp_debug_numsegments/sql/reset_numsegments.sql diff --git a/gpcontrib/Makefile b/gpcontrib/Makefile index 72355a7908..ff6c32c1e5 100644 --- a/gpcontrib/Makefile +++ b/gpcontrib/Makefile @@ -17,6 +17,7 @@ include $(top_builddir)/src/Makefile.global # targets built via top_builddir/GNUmakefile # recurse_targets = gp_sparse_vector \ + gp_debug_numsegments \ gp_distribution_policy \ gp_internal_tools \ gp_inject_fault diff --git a/gpcontrib/gp_debug_numsegments/Makefile b/gpcontrib/gp_debug_numsegments/Makefile new file mode 100644 index 0000000000..1758fcf0ba --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/Makefile @@ -0,0 +1,19 @@ +MODULE_big = gp_debug_numsegments + +EXTENSION = gp_debug_numsegments +DATA = gp_debug_numsegments--1.0.sql + +OBJS = gp_debug_numsegments.o +PG_CPPFLAGS = -I$(libpq_srcdir) + +REGRESS = default_numsegments reset_numsegments + +ifdef USE_PGXS +PGXS := $(shell pg_config --pgxs) +include $(PGXS) +else +subdir = contrib/gp_debug_numsegments +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/gpcontrib/gp_debug_numsegments/README.md b/gpcontrib/gp_debug_numsegments/README.md new file mode 100644 index 0000000000..b0121e3b85 --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/README.md @@ -0,0 +1,41 @@ +By default all tables are created on all the segments, with this extension we +could check or change the default behavior. + +How does it work? Each table has a property numsegments to record how many +segments its data is distributed one, the value is decided on `CREATE TABLE` +according to an internal variable `gp_create_table_default_numsegments`, its +value can be an integer number between `GP_POLICY_MINIMAL_NUMSEGMENTS` (always +be 1 in current implementation) and `GP_POLICY_ALL_NUMSEGMENTS` (all the +primary segments in the cluster), or one of below magic numbsers (policies): + +- `GP_DEFAULT_NUMSEGMENTS_FULL`: all the segments; +- `GP_DEFAULT_NUMSEGMENTS_MINIMAL`: the minimal set of segments; +- `GP_DEFAULT_NUMSEGMENTS_RANDOM`: pick a random set of segments each time; + +This extension provides functions to get, set and reset this internal +variable: + +- `gp_debug_set_create_table_default_numsegments(integer)`: + set the default numsegments to an integer number between 1 and + `gp_num_contents_in_cluster`; + +- `gp_debug_set_create_table_default_numsegments(text)`: + set the default numsegments to one of the policies: `FULL`, `MINIMAL` and + `RANDOM`; + +- `gp_debug_reset_create_table_default_numsegments(integer)` and + `gp_debug_reset_create_table_default_numsegments(text)`: + reset the default numsegments to the specified number or policy, the value + can be reused later; + +- `gp_debug_reset_create_table_default_numsegments()`: + reset the default numsegments to the last value passed in above two forms, + if there is no previous call to it the value is `FULL`; + +- `gp_debug_get_create_table_default_numsegments()`: + get the current number or policy of the default numsegments; + +The changes are effective within the session. + +As the name suggests, this extension should only be used for debugging +purpose. diff --git a/gpcontrib/gp_debug_numsegments/expected/default_numsegments.out b/gpcontrib/gp_debug_numsegments/expected/default_numsegments.out new file mode 100644 index 0000000000..6826fe48c5 --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/expected/default_numsegments.out @@ -0,0 +1,188 @@ +drop extension if exists gp_debug_numsegments; +NOTICE: extension "gp_debug_numsegments" does not exist, skipping +create extension gp_debug_numsegments; +-- +-- GOOD: valid text values: random, full, minimal +-- +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +create table t_default_first (c1 int, c2 int) distributed by (c1); +select gp_debug_set_create_table_default_numsegments('random'); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + RANDOM +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + RANDOM +(1 row) + +create table t_default_random (c1 int, c2 int) distributed by (c1); +select localoid::regclass, attrnums, policytype + from gp_distribution_policy + where localoid='t_default_random'::regclass + and numsegments between 1 and 3; + localoid | attrnums | policytype +------------------+----------+------------ + t_default_random | {1} | p +(1 row) + +drop table t_default_random; +select gp_debug_set_create_table_default_numsegments('full'); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +create table t_default_full (c1 int, c2 int) distributed by (c1); +select gp_debug_set_create_table_default_numsegments('minimal'); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + MINIMAL +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + MINIMAL +(1 row) + +create table t_default_minimal (c1 int, c2 int) distributed by (c1); +select gp_debug_set_create_table_default_numsegments('FULL'); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +create table "t_default_FULL" (c1 int, c2 int) distributed by (c1); +select gp_debug_set_create_table_default_numsegments('Full'); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +create table "t_default_Full" (c1 int, c2 int) distributed by (c1); +select gp_debug_set_create_table_default_numsegments('fulL'); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +create table "t_default_fulL" (c1 int, c2 int) distributed by (c1); +-- +-- GOOD: valid integer values between [1, gp_num_contents_in_cluster] +-- +select gp_debug_set_create_table_default_numsegments(1); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + 1 +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + 1 +(1 row) + +create table t_default_1 (c1 int, c2 int) distributed by (c1); +select gp_debug_set_create_table_default_numsegments(2); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + 2 +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + 2 +(1 row) + +create table t_default_2 (c1 int, c2 int) distributed by (c1); +select gp_debug_set_create_table_default_numsegments(3); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + 3 +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + 3 +(1 row) + +create table t_default_3 (c1 int, c2 int) distributed by (c1); +select c.relname, d.attrnums, d.policytype, d.numsegments + from gp_distribution_policy d + join pg_class c + on d.localoid=c.oid + and c.relname like 't_default_%'; + relname | attrnums | policytype | numsegments +-------------------+----------+------------+------------- + t_default_first | {1} | p | 3 + t_default_full | {1} | p | 3 + t_default_minimal | {1} | p | 1 + t_default_FULL | {1} | p | 3 + t_default_Full | {1} | p | 3 + t_default_fulL | {1} | p | 3 + t_default_1 | {1} | p | 1 + t_default_2 | {1} | p | 2 + t_default_3 | {1} | p | 3 +(9 rows) + +-- +-- BAD: syntax error +-- +select gp_debug_set_create_table_default_numsegments('reset'); +ERROR: invalid text value for default numsegments: 'reset' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_set_create_table_default_numsegments('unknown'); +ERROR: invalid text value for default numsegments: 'unknown' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_set_create_table_default_numsegments(' full'); +ERROR: invalid text value for default numsegments: ' full' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_set_create_table_default_numsegments('full '); +ERROR: invalid text value for default numsegments: 'full ' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_set_create_table_default_numsegments('1'); +ERROR: invalid text value for default numsegments: '1' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_set_create_table_default_numsegments(''); +ERROR: invalid text value for default numsegments: '' +HINT: Valid values: 'full', 'minimal', 'random' +-- +-- BAD: out of range +-- +select gp_debug_set_create_table_default_numsegments(0); +ERROR: invalid integer value for default numsegments: 0 +HINT: Valid range: [1, gp_num_contents_in_cluster] +select gp_debug_set_create_table_default_numsegments(-1); +ERROR: invalid integer value for default numsegments: -1 +HINT: Valid range: [1, gp_num_contents_in_cluster] +select gp_debug_set_create_table_default_numsegments(4); +ERROR: invalid integer value for default numsegments: 4 +HINT: Valid range: [1, gp_num_contents_in_cluster] +select gp_debug_set_create_table_default_numsegments(999); +ERROR: invalid integer value for default numsegments: 999 +HINT: Valid range: [1, gp_num_contents_in_cluster] +-- +-- BAD: cannot execute on segments +-- +select gp_debug_set_create_table_default_numsegments(1) + from gp_dist_random('gp_id'); +ERROR: function with EXECUTE ON restrictions cannot be used in the SELECT list of a query with FROM +select gp_debug_get_create_table_default_numsegments() + from gp_dist_random('gp_id'); +ERROR: function with EXECUTE ON restrictions cannot be used in the SELECT list of a query with FROM diff --git a/gpcontrib/gp_debug_numsegments/expected/reset_numsegments.out b/gpcontrib/gp_debug_numsegments/expected/reset_numsegments.out new file mode 100644 index 0000000000..db88d19e75 --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/expected/reset_numsegments.out @@ -0,0 +1,190 @@ +drop extension if exists gp_debug_numsegments; +create extension gp_debug_numsegments; +-- +-- GOOD: valid text values: random, full, minimal +-- +select gp_debug_reset_create_table_default_numsegments(); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +create table t_reset_first (c1 int, c2 int) distributed by (c1); +select gp_debug_reset_create_table_default_numsegments('random'); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + RANDOM +(1 row) + +create table t_reset_random (c1 int, c2 int) distributed by (c1); +select localoid::regclass, attrnums, policytype + from gp_distribution_policy + where localoid='t_reset_random'::regclass + and numsegments between 1 and 3; + localoid | attrnums | policytype +----------------+----------+------------ + t_reset_random | {1} | p +(1 row) + +drop table t_reset_random; +select gp_debug_reset_create_table_default_numsegments('full'); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +create table t_reset_full (c1 int, c2 int) distributed by (c1); +select gp_debug_reset_create_table_default_numsegments('minimal'); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + MINIMAL +(1 row) + +create table t_reset_minimal (c1 int, c2 int) distributed by (c1); +select gp_debug_reset_create_table_default_numsegments('FULL'); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +create table "t_reset_FULL" (c1 int, c2 int) distributed by (c1); +select gp_debug_reset_create_table_default_numsegments('Full'); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +create table "t_reset_Full" (c1 int, c2 int) distributed by (c1); +select gp_debug_reset_create_table_default_numsegments('fulL'); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +create table "t_reset_fulL" (c1 int, c2 int) distributed by (c1); +-- +-- GOOD: valid integer values between [1, gp_num_contents_in_cluster] +-- +select gp_debug_reset_create_table_default_numsegments(1); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + 1 +(1 row) + +create table t_reset_1 (c1 int, c2 int) distributed by (c1); +select gp_debug_reset_create_table_default_numsegments(2); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + 2 +(1 row) + +create table t_reset_2 (c1 int, c2 int) distributed by (c1); +select gp_debug_reset_create_table_default_numsegments(3); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + +select gp_debug_get_create_table_default_numsegments(); + gp_debug_get_create_table_default_numsegments +----------------------------------------------- + 3 +(1 row) + +create table t_reset_3 (c1 int, c2 int) distributed by (c1); +select c.relname, d.attrnums, d.policytype, d.numsegments + from gp_distribution_policy d + join pg_class c + on d.localoid=c.oid + and c.relname like 't_reset_%'; + relname | attrnums | policytype | numsegments +-----------------+----------+------------+------------- + t_reset_first | {1} | p | 3 + t_reset_full | {1} | p | 3 + t_reset_minimal | {1} | p | 1 + t_reset_FULL | {1} | p | 3 + t_reset_Full | {1} | p | 3 + t_reset_fulL | {1} | p | 3 + t_reset_1 | {1} | p | 1 + t_reset_2 | {1} | p | 2 + t_reset_3 | {1} | p | 3 +(9 rows) + +-- +-- BAD: syntax error +-- +select gp_debug_reset_create_table_default_numsegments('reset'); +ERROR: invalid text value for default numsegments: 'reset' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_reset_create_table_default_numsegments('unknown'); +ERROR: invalid text value for default numsegments: 'unknown' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_reset_create_table_default_numsegments(' full'); +ERROR: invalid text value for default numsegments: ' full' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_reset_create_table_default_numsegments('full '); +ERROR: invalid text value for default numsegments: 'full ' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_reset_create_table_default_numsegments('1'); +ERROR: invalid text value for default numsegments: '1' +HINT: Valid values: 'full', 'minimal', 'random' +select gp_debug_reset_create_table_default_numsegments(''); +ERROR: invalid text value for default numsegments: '' +HINT: Valid values: 'full', 'minimal', 'random' +-- +-- BAD: out of range +-- +select gp_debug_reset_create_table_default_numsegments(0); +ERROR: invalid integer value for default numsegments: 0 +HINT: Valid range: [1, gp_num_contents_in_cluster] +select gp_debug_reset_create_table_default_numsegments(-1); +ERROR: invalid integer value for default numsegments: -1 +HINT: Valid range: [1, gp_num_contents_in_cluster] +select gp_debug_reset_create_table_default_numsegments(4); +ERROR: invalid integer value for default numsegments: 4 +HINT: Valid range: [1, gp_num_contents_in_cluster] +select gp_debug_reset_create_table_default_numsegments(999); +ERROR: invalid integer value for default numsegments: 999 +HINT: Valid range: [1, gp_num_contents_in_cluster] +-- +-- BAD: cannot execute on segments +-- +select gp_debug_reset_create_table_default_numsegments(1) + from gp_dist_random('gp_id'); +ERROR: function with EXECUTE ON restrictions cannot be used in the SELECT list of a query with FROM diff --git a/gpcontrib/gp_debug_numsegments/gp_debug_numsegments--1.0.sql b/gpcontrib/gp_debug_numsegments/gp_debug_numsegments--1.0.sql new file mode 100644 index 0000000000..04fb8ff1ed --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/gp_debug_numsegments--1.0.sql @@ -0,0 +1,38 @@ +/* contrib/gp_debug_numsegments/gp_debug_numsegments--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION gp_debug_numsegments" to load this file. \quit + +SET search_path = public; + +-- This function set the default numsegments when creating tables. +-- This form accepts a text argument: 'full', 'minimal', 'random'. +CREATE OR REPLACE FUNCTION gp_debug_set_create_table_default_numsegments(text) RETURNS text +AS '$libdir/gp_debug_numsegments','gp_debug_set_create_table_default_numsegments' +LANGUAGE C IMMUTABLE STRICT EXECUTE ON MASTER; +-- This form accepts an integer argument: [1, gp_num_contents_in_cluster]. +CREATE OR REPLACE FUNCTION gp_debug_set_create_table_default_numsegments(integer) RETURNS text +AS '$libdir/gp_debug_numsegments','gp_debug_set_create_table_default_numsegments' +LANGUAGE C IMMUTABLE STRICT EXECUTE ON MASTER; + +-- This function reset the default numsegments. +-- This form accepts a text argument: 'full', 'minimal' or 'random', +-- numsegments will be reset to this value since this time. +CREATE OR REPLACE FUNCTION gp_debug_reset_create_table_default_numsegments(text) RETURNS void +AS '$libdir/gp_debug_numsegments','gp_debug_reset_create_table_default_numsegments' +LANGUAGE C IMMUTABLE STRICT EXECUTE ON MASTER; +-- This form accepts an integer argument: [1, gp_num_contents_in_cluster], +-- numsegments will be reset to this value since this time. +CREATE OR REPLACE FUNCTION gp_debug_reset_create_table_default_numsegments(integer) RETURNS void +AS '$libdir/gp_debug_numsegments','gp_debug_reset_create_table_default_numsegments' +LANGUAGE C IMMUTABLE STRICT EXECUTE ON MASTER; +-- This form resets numsegments directly, the value is decided by last reset, +-- or FULL if reset is never executed. +CREATE OR REPLACE FUNCTION gp_debug_reset_create_table_default_numsegments() RETURNS void +AS '$libdir/gp_debug_numsegments','gp_debug_reset_create_table_default_numsegments' +LANGUAGE C IMMUTABLE STRICT EXECUTE ON MASTER; + +-- This function get the default numsegments when creating tables. +CREATE OR REPLACE FUNCTION gp_debug_get_create_table_default_numsegments() RETURNS text +AS '$libdir/gp_debug_numsegments','gp_debug_get_create_table_default_numsegments' +LANGUAGE C IMMUTABLE STRICT EXECUTE ON MASTER; diff --git a/gpcontrib/gp_debug_numsegments/gp_debug_numsegments.c b/gpcontrib/gp_debug_numsegments/gp_debug_numsegments.c new file mode 100644 index 0000000000..266e51f008 --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/gp_debug_numsegments.c @@ -0,0 +1,162 @@ +/*------------------------------------------------------------------------- + * + * gp_debug_numsegments.c + * Debugging helpers to get / set default numsegment when creating tables. + * + * + * Copyright (c) 2018-Present Pivotal Software, Inc. + * + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "fmgr.h" +#include "utils/builtins.h" +#include "cdb/cdbutil.h" +#include "catalog/gp_policy.h" + + +#ifdef PG_MODULE_MAGIC +PG_MODULE_MAGIC; +#endif + +extern Datum gp_debug_set_create_table_default_numsegments(PG_FUNCTION_ARGS); +extern Datum gp_debug_reset_create_table_default_numsegments(PG_FUNCTION_ARGS); +extern Datum gp_debug_get_create_table_default_numsegments(PG_FUNCTION_ARGS); + +PG_FUNCTION_INFO_V1(gp_debug_set_create_table_default_numsegments); +PG_FUNCTION_INFO_V1(gp_debug_reset_create_table_default_numsegments); +PG_FUNCTION_INFO_V1(gp_debug_get_create_table_default_numsegments); + +static int reset_numsegments = GP_DEFAULT_NUMSEGMENTS_FULL; + +/* + * Set the default numsegments when creating tables. + * + * It accepts one argument, in text or integer format. + * + * Valid values for text argument: + * - 'FULL': all the segments; + * - 'RANDOM': pick a random set of segments each time; + * - 'MINIMAL': the minimal set of segments; + * + * For integer argument the valid range is [1, gp_num_contents_in_cluster]. + */ +Datum +gp_debug_set_create_table_default_numsegments(PG_FUNCTION_ARGS) +{ + Oid argtypeoid = InvalidOid; + const char *str = NULL; + int numsegments = -1; + + Assert(1 == PG_NARGS()); + + argtypeoid = get_fn_expr_argtype(fcinfo->flinfo, 0); + + /* Accept argument in integer / text format */ + Assert(argtypeoid == INT4OID || argtypeoid == TEXTOID); + + if (argtypeoid == INT4OID) + { + numsegments = PG_GETARG_INT32(0); + } + else + { + str = text_to_cstring(PG_GETARG_TEXT_P(0)); + Assert(str != NULL); + } + + if (str == NULL) + { + if (numsegments < GP_POLICY_MINIMAL_NUMSEGMENTS || + numsegments > GP_POLICY_ALL_NUMSEGMENTS) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("invalid integer value for default numsegments: %d", + numsegments), + errhint("Valid range: [1, %d (gp_num_contents_in_cluster)]", + GP_POLICY_ALL_NUMSEGMENTS))); + + gp_create_table_default_numsegments = numsegments; + } + else if (pg_strcasecmp(str, "full") == 0) + gp_create_table_default_numsegments = GP_DEFAULT_NUMSEGMENTS_FULL; + else if (pg_strcasecmp(str, "random") == 0) + gp_create_table_default_numsegments = GP_DEFAULT_NUMSEGMENTS_RANDOM; + else if (pg_strcasecmp(str, "minimal") == 0) + gp_create_table_default_numsegments = GP_DEFAULT_NUMSEGMENTS_MINIMAL; + else + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("invalid text value for default numsegments: '%s'", str), + errhint("Valid values: 'full', 'minimal', 'random'"))); + } + + return gp_debug_get_create_table_default_numsegments(fcinfo); +} + +/* + * Reset the default numsegments when creating tables. + * + * It accepts zero or one argument, in text or integer format. + * + * Valid values for text argument: + * - 'FULL': all the segments; + * - 'RANDOM': pick a random set of segments each time; + * - 'MINIMAL': the minimal set of segments; + * + * For integer argument the valid range is [1, gp_num_contents_in_cluster]. + * + * When there is zero argument it reset the default numsegments directly. + */ +Datum +gp_debug_reset_create_table_default_numsegments(PG_FUNCTION_ARGS) +{ + if (1 == PG_NARGS()) + { + gp_debug_set_create_table_default_numsegments(fcinfo); + + reset_numsegments = gp_create_table_default_numsegments; + } + else + { + Assert(0 == PG_NARGS()); + + gp_create_table_default_numsegments = reset_numsegments; + } + + PG_RETURN_VOID(); +} + +/* + * Get the default numsegments when creating a table. + */ +Datum +gp_debug_get_create_table_default_numsegments(PG_FUNCTION_ARGS) +{ + char buf[64]; + const char *result = NULL; + + switch (gp_create_table_default_numsegments) + { + case GP_DEFAULT_NUMSEGMENTS_FULL: + result = "FULL"; + break; + case GP_DEFAULT_NUMSEGMENTS_RANDOM: + result = "RANDOM"; + break; + case GP_DEFAULT_NUMSEGMENTS_MINIMAL: + result = "MINIMAL"; + break; + default: + snprintf(buf, sizeof(buf), "%d", + gp_create_table_default_numsegments); + result = buf; + break; + } + + PG_RETURN_DATUM(CStringGetTextDatum(result)); +} diff --git a/gpcontrib/gp_debug_numsegments/gp_debug_numsegments.control b/gpcontrib/gp_debug_numsegments/gp_debug_numsegments.control new file mode 100644 index 0000000000..fee8da81a5 --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/gp_debug_numsegments.control @@ -0,0 +1,5 @@ +# gp_debug_numsegments extension +comment = 'get / set default numsegments when creating tables' +default_version = '1.0' +module_pathname = '$libdir/gp_debug_numsegments' +relocatable = true diff --git a/gpcontrib/gp_debug_numsegments/sql/default_numsegments.sql b/gpcontrib/gp_debug_numsegments/sql/default_numsegments.sql new file mode 100644 index 0000000000..145c8d8419 --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/sql/default_numsegments.sql @@ -0,0 +1,86 @@ +drop extension if exists gp_debug_numsegments; +create extension gp_debug_numsegments; + +-- +-- GOOD: valid text values: random, full, minimal +-- + +select gp_debug_get_create_table_default_numsegments(); +create table t_default_first (c1 int, c2 int) distributed by (c1); + +select gp_debug_set_create_table_default_numsegments('random'); +select gp_debug_get_create_table_default_numsegments(); +create table t_default_random (c1 int, c2 int) distributed by (c1); +select localoid::regclass, attrnums, policytype + from gp_distribution_policy + where localoid='t_default_random'::regclass + and numsegments between 1 and 3; +drop table t_default_random; + +select gp_debug_set_create_table_default_numsegments('full'); +select gp_debug_get_create_table_default_numsegments(); +create table t_default_full (c1 int, c2 int) distributed by (c1); + +select gp_debug_set_create_table_default_numsegments('minimal'); +select gp_debug_get_create_table_default_numsegments(); +create table t_default_minimal (c1 int, c2 int) distributed by (c1); + +select gp_debug_set_create_table_default_numsegments('FULL'); +create table "t_default_FULL" (c1 int, c2 int) distributed by (c1); + +select gp_debug_set_create_table_default_numsegments('Full'); +create table "t_default_Full" (c1 int, c2 int) distributed by (c1); + +select gp_debug_set_create_table_default_numsegments('fulL'); +create table "t_default_fulL" (c1 int, c2 int) distributed by (c1); + +-- +-- GOOD: valid integer values between [1, gp_num_contents_in_cluster] +-- + +select gp_debug_set_create_table_default_numsegments(1); +select gp_debug_get_create_table_default_numsegments(); +create table t_default_1 (c1 int, c2 int) distributed by (c1); + +select gp_debug_set_create_table_default_numsegments(2); +select gp_debug_get_create_table_default_numsegments(); +create table t_default_2 (c1 int, c2 int) distributed by (c1); + +select gp_debug_set_create_table_default_numsegments(3); +select gp_debug_get_create_table_default_numsegments(); +create table t_default_3 (c1 int, c2 int) distributed by (c1); + +select c.relname, d.attrnums, d.policytype, d.numsegments + from gp_distribution_policy d + join pg_class c + on d.localoid=c.oid + and c.relname like 't_default_%'; + +-- +-- BAD: syntax error +-- + +select gp_debug_set_create_table_default_numsegments('reset'); +select gp_debug_set_create_table_default_numsegments('unknown'); +select gp_debug_set_create_table_default_numsegments(' full'); +select gp_debug_set_create_table_default_numsegments('full '); +select gp_debug_set_create_table_default_numsegments('1'); +select gp_debug_set_create_table_default_numsegments(''); + +-- +-- BAD: out of range +-- + +select gp_debug_set_create_table_default_numsegments(0); +select gp_debug_set_create_table_default_numsegments(-1); +select gp_debug_set_create_table_default_numsegments(4); +select gp_debug_set_create_table_default_numsegments(999); + +-- +-- BAD: cannot execute on segments +-- + +select gp_debug_set_create_table_default_numsegments(1) + from gp_dist_random('gp_id'); +select gp_debug_get_create_table_default_numsegments() + from gp_dist_random('gp_id'); diff --git a/gpcontrib/gp_debug_numsegments/sql/reset_numsegments.sql b/gpcontrib/gp_debug_numsegments/sql/reset_numsegments.sql new file mode 100644 index 0000000000..64fb8a1a74 --- /dev/null +++ b/gpcontrib/gp_debug_numsegments/sql/reset_numsegments.sql @@ -0,0 +1,85 @@ +drop extension if exists gp_debug_numsegments; +create extension gp_debug_numsegments; + +-- +-- GOOD: valid text values: random, full, minimal +-- + +select gp_debug_reset_create_table_default_numsegments(); +select gp_debug_get_create_table_default_numsegments(); +create table t_reset_first (c1 int, c2 int) distributed by (c1); + +select gp_debug_reset_create_table_default_numsegments('random'); +select gp_debug_get_create_table_default_numsegments(); +create table t_reset_random (c1 int, c2 int) distributed by (c1); +select localoid::regclass, attrnums, policytype + from gp_distribution_policy + where localoid='t_reset_random'::regclass + and numsegments between 1 and 3; +drop table t_reset_random; + +select gp_debug_reset_create_table_default_numsegments('full'); +select gp_debug_get_create_table_default_numsegments(); +create table t_reset_full (c1 int, c2 int) distributed by (c1); + +select gp_debug_reset_create_table_default_numsegments('minimal'); +select gp_debug_get_create_table_default_numsegments(); +create table t_reset_minimal (c1 int, c2 int) distributed by (c1); + +select gp_debug_reset_create_table_default_numsegments('FULL'); +create table "t_reset_FULL" (c1 int, c2 int) distributed by (c1); + +select gp_debug_reset_create_table_default_numsegments('Full'); +create table "t_reset_Full" (c1 int, c2 int) distributed by (c1); + +select gp_debug_reset_create_table_default_numsegments('fulL'); +create table "t_reset_fulL" (c1 int, c2 int) distributed by (c1); + +-- +-- GOOD: valid integer values between [1, gp_num_contents_in_cluster] +-- + +select gp_debug_reset_create_table_default_numsegments(1); +select gp_debug_get_create_table_default_numsegments(); +create table t_reset_1 (c1 int, c2 int) distributed by (c1); + +select gp_debug_reset_create_table_default_numsegments(2); +select gp_debug_get_create_table_default_numsegments(); +create table t_reset_2 (c1 int, c2 int) distributed by (c1); + +select gp_debug_reset_create_table_default_numsegments(3); +select gp_debug_get_create_table_default_numsegments(); +create table t_reset_3 (c1 int, c2 int) distributed by (c1); + +select c.relname, d.attrnums, d.policytype, d.numsegments + from gp_distribution_policy d + join pg_class c + on d.localoid=c.oid + and c.relname like 't_reset_%'; + +-- +-- BAD: syntax error +-- + +select gp_debug_reset_create_table_default_numsegments('reset'); +select gp_debug_reset_create_table_default_numsegments('unknown'); +select gp_debug_reset_create_table_default_numsegments(' full'); +select gp_debug_reset_create_table_default_numsegments('full '); +select gp_debug_reset_create_table_default_numsegments('1'); +select gp_debug_reset_create_table_default_numsegments(''); + +-- +-- BAD: out of range +-- + +select gp_debug_reset_create_table_default_numsegments(0); +select gp_debug_reset_create_table_default_numsegments(-1); +select gp_debug_reset_create_table_default_numsegments(4); +select gp_debug_reset_create_table_default_numsegments(999); + +-- +-- BAD: cannot execute on segments +-- + +select gp_debug_reset_create_table_default_numsegments(1) + from gp_dist_random('gp_id'); diff --git a/src/backend/cdb/cdbcat.c b/src/backend/cdb/cdbcat.c index 3e6adacf3f..df31723b7c 100644 --- a/src/backend/cdb/cdbcat.c +++ b/src/backend/cdb/cdbcat.c @@ -32,6 +32,21 @@ #include "utils/tqual.h" #include "utils/syscache.h" +/* + * The default numsegments when creating tables. The value can be an integer + * between GP_POLICY_MINIMAL_NUMSEGMENTS and GP_POLICY_ALL_NUMSEGMENTS or one + * of below magic numbers: + * + * - GP_DEFAULT_NUMSEGMENTS_FULL: all the segments; + * - GP_DEFAULT_NUMSEGMENTS_RANDOM: pick a random set of segments each time; + * - GP_DEFAULT_NUMSEGMENTS_MINIMAL: the minimal set of segments; + * + * A wrapper macro GP_POLICY_DEFAULT_NUMSEGMENTS is defined to get the default + * numsegments according to the setting of this variable, always use that macro + * instead of this variable. + */ +int gp_create_table_default_numsegments = GP_DEFAULT_NUMSEGMENTS_FULL; + static void extract_INT2OID_array(Datum array_datum, int *lenp, int16 **vecp); GpPolicy * diff --git a/src/backend/cdb/cdbmutate.c b/src/backend/cdb/cdbmutate.c index f1c448f0d4..9c5deeecba 100644 --- a/src/backend/cdb/cdbmutate.c +++ b/src/backend/cdb/cdbmutate.c @@ -28,6 +28,7 @@ #include "optimizer/var.h" #include "parser/parse_relation.h" #include "utils/fmgroids.h" +#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/datum.h" #include "utils/syscache.h" @@ -285,10 +286,10 @@ apply_motion(PlannerInfo *root, Plan *plan, Query *query) /* * In CTAS the source distribution policy is not inherited, - * always set numsegments to ALL unless a DISTRIBUTED BY clause - * is specified. + * always set numsegments to DEFAULT unless a DISTRIBUTED BY + * clause is specified. */ - numsegments = GP_POLICY_ALL_NUMSEGMENTS; + numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS; if (query->intoPolicy != NULL) { diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index abb3729a94..0edd4759fa 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -3667,7 +3667,7 @@ setQryDistributionPolicy(IntoClause *into, Query *qry) dist = (DistributedBy *)into->distributedBy; if (dist->numsegments < 0) - dist->numsegments = GP_POLICY_ALL_NUMSEGMENTS; + dist->numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS; /* * We have a DISTRIBUTED BY column list specified by the user diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 27a74d4ecc..5db473813b 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -1672,7 +1672,7 @@ transformCreateExternalStmt(CreateExternalStmt *stmt, const char *queryString) stmt->distributedBy = makeNode(DistributedBy); stmt->distributedBy->ptype = POLICYTYPE_PARTITIONED; stmt->distributedBy->keys = NIL; - stmt->distributedBy->numsegments = GP_POLICY_ALL_NUMSEGMENTS; + stmt->distributedBy->numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS; } else { @@ -1725,7 +1725,7 @@ transformDistributedBy(CreateStmtContext *cxt, ListCell *keys = NULL; List *distrkeys = NIL; /* By default tables should be distributed on ALL segments */ - int numsegments = GP_POLICY_ALL_NUMSEGMENTS; + int numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS; ListCell *lc; /* @@ -1738,7 +1738,7 @@ transformDistributedBy(CreateStmtContext *cxt, if (distributedBy && (distributedBy->ptype == POLICYTYPE_PARTITIONED && distributedBy->keys == NIL)) { - distributedBy->numsegments = GP_POLICY_ALL_NUMSEGMENTS; + distributedBy->numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS; return distributedBy; } @@ -1750,7 +1750,7 @@ transformDistributedBy(CreateStmtContext *cxt, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("INHERITS clause cannot be used with DISTRIBUTED REPLICATED clause"))); - distributedBy->numsegments = GP_POLICY_ALL_NUMSEGMENTS; + distributedBy->numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS; return distributedBy; } @@ -1946,7 +1946,7 @@ transformDistributedBy(CreateStmtContext *cxt, /* * Create with default distribution policy and numsegments. */ - numsegments = GP_POLICY_ALL_NUMSEGMENTS; + numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS; distributedBy = makeNode(DistributedBy); distributedBy->ptype = POLICYTYPE_PARTITIONED; @@ -2056,7 +2056,7 @@ transformDistributedBy(CreateStmtContext *cxt, /* * Create with default distribution policy and numsegments. */ - numsegments = GP_POLICY_ALL_NUMSEGMENTS; + numsegments = GP_POLICY_DEFAULT_NUMSEGMENTS; distributedBy = makeNode(DistributedBy); distributedBy->ptype = POLICYTYPE_PARTITIONED; diff --git a/src/include/catalog/gp_policy.h b/src/include/catalog/gp_policy.h index 1f328e61df..632f0d8a2a 100644 --- a/src/include/catalog/gp_policy.h +++ b/src/include/catalog/gp_policy.h @@ -63,6 +63,42 @@ FOREIGN_KEY(localoid REFERENCES pg_class(oid)); */ #define GP_POLICY_ALL_NUMSEGMENTS Max(1, getgpsegmentCount()) +/* + * Minimal set of segments. + */ +#define GP_POLICY_MINIMAL_NUMSEGMENTS 1 + +/* + * A random set of segments, the value is different on each call. + */ +#define GP_POLICY_RANDOM_NUMSEGMENTS \ + (GP_POLICY_MINIMAL_NUMSEGMENTS + \ + random() % (GP_POLICY_ALL_NUMSEGMENTS - GP_POLICY_MINIMAL_NUMSEGMENTS + 1)) + +/* + * Default set of segments, the value is controlled by the variable + * gp_create_table_default_numsegments. + */ +#define GP_POLICY_DEFAULT_NUMSEGMENTS \ +( gp_create_table_default_numsegments == GP_DEFAULT_NUMSEGMENTS_FULL ? GP_POLICY_ALL_NUMSEGMENTS \ +: gp_create_table_default_numsegments == GP_DEFAULT_NUMSEGMENTS_RANDOM ? GP_POLICY_RANDOM_NUMSEGMENTS \ +: gp_create_table_default_numsegments == GP_DEFAULT_NUMSEGMENTS_MINIMAL ? GP_POLICY_MINIMAL_NUMSEGMENTS \ +: gp_create_table_default_numsegments ) + +/* + * The the default numsegments policies when creating a table. + * + * - FULL: all the segments; + * - RANDOM: pick a random set of segments each time; + * - MINIMAL: the minimal set of segments; + */ +enum +{ + GP_DEFAULT_NUMSEGMENTS_FULL = -1, + GP_DEFAULT_NUMSEGMENTS_RANDOM = -2, + GP_DEFAULT_NUMSEGMENTS_MINIMAL = -3, +}; + /* * The segments suitable for Entry locus, which include both master and all * the segments. @@ -103,6 +139,11 @@ typedef struct GpPolicy AttrNumber *attrs; /* pointer to the first of nattrs attribute numbers. */ } GpPolicy; +/* + * Global Variables + */ +extern int gp_create_table_default_numsegments; + /* * GpPolicyCopy -- Return a copy of a GpPolicy object. * diff --git a/src/test/regress/expected/partial_table.out b/src/test/regress/expected/partial_table.out index c98ddcb47f..894fb5bb22 100644 --- a/src/test/regress/expected/partial_table.out +++ b/src/test/regress/expected/partial_table.out @@ -3,20 +3,38 @@ -- TODO: ao tables -- TODO: tables and temp tables \set explain 'explain analyze' -set allow_system_table_mods to true; +create extension if not exists gp_debug_numsegments; +drop schema if exists test_partial_table; +NOTICE: schema "test_partial_table" does not exist, skipping +create schema test_partial_table; +set search_path=test_partial_table,public; -- -- prepare kinds of tables -- -create temp table t1 (c1 int, c2 int, c3 int, c4 int) distributed by (c1, c2); -create temp table d1 (c1 int, c2 int, c3 int, c4 int) distributed replicated; -create temp table r1 (c1 int, c2 int, c3 int, c4 int) distributed randomly; -create temp table t2 (c1 int, c2 int, c3 int, c4 int) distributed by (c1, c2); -create temp table d2 (c1 int, c2 int, c3 int, c4 int) distributed replicated; -create temp table r2 (c1 int, c2 int, c3 int, c4 int) distributed randomly; -update gp_distribution_policy set numsegments=1 - where localoid in ('t1'::regclass, 'd1'::regclass, 'r1'::regclass); -update gp_distribution_policy set numsegments=2 - where localoid in ('t2'::regclass, 'd2'::regclass, 'r2'::regclass); +select gp_debug_set_create_table_default_numsegments(1); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + 1 +(1 row) + +create table t1 (c1 int, c2 int, c3 int, c4 int) distributed by (c1, c2); +create table d1 (c1 int, c2 int, c3 int, c4 int) distributed replicated; +create table r1 (c1 int, c2 int, c3 int, c4 int) distributed randomly; +select gp_debug_set_create_table_default_numsegments(2); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + 2 +(1 row) + +create table t2 (c1 int, c2 int, c3 int, c4 int) distributed by (c1, c2); +create table d2 (c1 int, c2 int, c3 int, c4 int) distributed replicated; +create table r2 (c1 int, c2 int, c3 int, c4 int) distributed randomly; +select gp_debug_reset_create_table_default_numsegments(); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ( 't1'::regclass, 'd1'::regclass, 'r1'::regclass, @@ -82,7 +100,7 @@ analyze t1; -- -- create table -- -create temp table t (like t1); +create table t (like t1); NOTICE: Table doesn't have 'DISTRIBUTED BY' clause, defaulting to distribution columns from LIKE table select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); @@ -92,7 +110,15 @@ select localoid::regclass, attrnums, policytype, numsegments (1 row) drop table t; -create temp table t as table t1; +-- CTAS set numsegments with DEFAULT, +-- let it be a fixed value to get stable output +select gp_debug_set_create_table_default_numsegments('full'); + gp_debug_set_create_table_default_numsegments +----------------------------------------------- + FULL +(1 row) + +create table t as table t1; NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'c1, c2' as the Greenplum Database data distribution key for this table. HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. select localoid::regclass, attrnums, policytype, numsegments @@ -103,7 +129,7 @@ select localoid::regclass, attrnums, policytype, numsegments (1 row) drop table t; -create temp table t as select * from t1; +create table t as select * from t1; NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'c1, c2' as the Greenplum Database data distribution key for this table. HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. select localoid::regclass, attrnums, policytype, numsegments @@ -114,7 +140,7 @@ select localoid::regclass, attrnums, policytype, numsegments (1 row) drop table t; -create temp table t as select * from t1 distributed by (c1, c2); +create table t as select * from t1 distributed by (c1, c2); select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); localoid | attrnums | policytype | numsegments @@ -123,7 +149,7 @@ select localoid::regclass, attrnums, policytype, numsegments (1 row) drop table t; -create temp table t as select * from t1 distributed replicated; +create table t as select * from t1 distributed replicated; select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); localoid | attrnums | policytype | numsegments @@ -132,7 +158,7 @@ select localoid::regclass, attrnums, policytype, numsegments (1 row) drop table t; -create temp table t as select * from t1 distributed randomly; +create table t as select * from t1 distributed randomly; select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); localoid | attrnums | policytype | numsegments @@ -141,7 +167,7 @@ select localoid::regclass, attrnums, policytype, numsegments (1 row) drop table t; -select * into temp table t from t1; +select * into table t from t1; NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column(s) named 'c1, c2' as the Greenplum Database data distribution key for this table. HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew. select localoid::regclass, attrnums, policytype, numsegments @@ -152,6 +178,12 @@ select localoid::regclass, attrnums, policytype, numsegments (1 row) drop table t; +select gp_debug_reset_create_table_default_numsegments(); + gp_debug_reset_create_table_default_numsegments +------------------------------------------------- + +(1 row) + -- -- alter table -- diff --git a/src/test/regress/greenplum_schedule b/src/test/regress/greenplum_schedule index 6a4be810f5..032b30bacf 100755 --- a/src/test/regress/greenplum_schedule +++ b/src/test/regress/greenplum_schedule @@ -43,9 +43,6 @@ test: icudp/gp_interconnect_queue_depth icudp/gp_interconnect_queue_depth_longti # event triggers cannot run concurrently with any test that runs DDL test: event_trigger_gp -# test partially distributed tables -test: partial_table - # deadlock tests run separately - because we don't know which one gets stuck. test: deadlock @@ -77,7 +74,7 @@ test: dtm_retry # The appendonly test cannot be run concurrently with tests that have # serializable transactions (may conflict with AO vacuum operations). -test: rangefuncs_cdb gp_dqa subselect_gp subselect_gp2 gp_transactions olap_group olap_window_seq sirv_functions appendonly create_table_distpol alter_distpol_dropped query_finish +test: rangefuncs_cdb gp_dqa subselect_gp subselect_gp2 gp_transactions olap_group olap_window_seq sirv_functions appendonly create_table_distpol alter_distpol_dropped query_finish partial_table # 'partition' runs for a long time, so try to keep it together with other # long-running tests. diff --git a/src/test/regress/sql/partial_table.sql b/src/test/regress/sql/partial_table.sql index 9a96fac940..d70f97f730 100644 --- a/src/test/regress/sql/partial_table.sql +++ b/src/test/regress/sql/partial_table.sql @@ -5,25 +5,27 @@ \set explain 'explain analyze' -set allow_system_table_mods to true; +create extension if not exists gp_debug_numsegments; + +drop schema if exists test_partial_table; +create schema test_partial_table; +set search_path=test_partial_table,public; -- -- prepare kinds of tables -- -create temp table t1 (c1 int, c2 int, c3 int, c4 int) distributed by (c1, c2); -create temp table d1 (c1 int, c2 int, c3 int, c4 int) distributed replicated; -create temp table r1 (c1 int, c2 int, c3 int, c4 int) distributed randomly; - -create temp table t2 (c1 int, c2 int, c3 int, c4 int) distributed by (c1, c2); -create temp table d2 (c1 int, c2 int, c3 int, c4 int) distributed replicated; -create temp table r2 (c1 int, c2 int, c3 int, c4 int) distributed randomly; +select gp_debug_set_create_table_default_numsegments(1); +create table t1 (c1 int, c2 int, c3 int, c4 int) distributed by (c1, c2); +create table d1 (c1 int, c2 int, c3 int, c4 int) distributed replicated; +create table r1 (c1 int, c2 int, c3 int, c4 int) distributed randomly; -update gp_distribution_policy set numsegments=1 - where localoid in ('t1'::regclass, 'd1'::regclass, 'r1'::regclass); +select gp_debug_set_create_table_default_numsegments(2); +create table t2 (c1 int, c2 int, c3 int, c4 int) distributed by (c1, c2); +create table d2 (c1 int, c2 int, c3 int, c4 int) distributed replicated; +create table r2 (c1 int, c2 int, c3 int, c4 int) distributed randomly; -update gp_distribution_policy set numsegments=2 - where localoid in ('t2'::regclass, 'd2'::regclass, 'r2'::regclass); +select gp_debug_reset_create_table_default_numsegments(); select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ( @@ -57,41 +59,47 @@ analyze t1; -- create table -- -create temp table t (like t1); +create table t (like t1); select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); drop table t; -create temp table t as table t1; +-- CTAS set numsegments with DEFAULT, +-- let it be a fixed value to get stable output +select gp_debug_set_create_table_default_numsegments('full'); + +create table t as table t1; select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); drop table t; -create temp table t as select * from t1; +create table t as select * from t1; select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); drop table t; -create temp table t as select * from t1 distributed by (c1, c2); +create table t as select * from t1 distributed by (c1, c2); select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); drop table t; -create temp table t as select * from t1 distributed replicated; +create table t as select * from t1 distributed replicated; select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); drop table t; -create temp table t as select * from t1 distributed randomly; +create table t as select * from t1 distributed randomly; select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); drop table t; -select * into temp table t from t1; +select * into table t from t1; select localoid::regclass, attrnums, policytype, numsegments from gp_distribution_policy where localoid in ('t'::regclass); drop table t; +select gp_debug_reset_create_table_default_numsegments(); + -- -- alter table -- @@ -300,6 +308,7 @@ drop table t; :explain select * from r2 a left join r2 b using (c1); :explain select * from r2 a left join r2 b using (c1, c2); :explain select * from t1, t2 where t1.c1 > any (select max(t2.c1) from t2 where t2.c2 = t1.c2) and t2.c1 > any(select max(c1) from t1 where t1.c2 = t2.c2); + -- -- insert -- -- GitLab