未验证 提交 3119009a 编写于 作者: N Ning Yu 提交者: GitHub

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.
上级 e576c0b9
......@@ -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
......
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
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.
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
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
/* 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;
/*-------------------------------------------------------------------------
*
* 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));
}
# gp_debug_numsegments extension
comment = 'get / set default numsegments when creating tables'
default_version = '1.0'
module_pathname = '$libdir/gp_debug_numsegments'
relocatable = true
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');
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');
......@@ -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 *
......
......@@ -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)
{
......
......@@ -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
......
......@@ -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;
......
......@@ -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.
*
......
......@@ -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
--
......
......@@ -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.
......
......@@ -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
--
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册