Merged in enordstr/backend-database/enordstr/tablespaces (pull request #63)

Add support for tablespaces
This commit is contained in:
enordstr NA 2017-01-31 10:07:09 +00:00
commit 1523ad89c6
17 changed files with 302 additions and 32 deletions

View File

@ -9,7 +9,8 @@ CREATE OR REPLACE FUNCTION _iobeamdb_meta_api.create_hypertable(
associated_schema_name NAME,
associated_table_prefix NAME,
placement _iobeamdb_catalog.chunk_placement_type,
chunk_size_bytes BIGINT
chunk_size_bytes BIGINT,
tablespace NAME
)
RETURNS _iobeamdb_catalog.hypertable LANGUAGE PLPGSQL VOLATILE AS
$BODY$
@ -19,7 +20,7 @@ BEGIN
SELECT (res::_iobeamdb_catalog.hypertable).*
INTO hypertable_row
FROM _iobeamdb_internal.meta_transaction_exec_with_return(
format('SELECT t FROM _iobeamdb_meta.create_hypertable(%L, %L, %L, %L, %L, %L, %L, %L, %L, %L, %L, %L) t ',
format('SELECT t FROM _iobeamdb_meta.create_hypertable(%L, %L, %L, %L, %L, %L, %L, %L, %L, %L, %L, %L, %L) t ',
main_schema_name,
main_table_name,
time_column_name,
@ -31,6 +32,7 @@ BEGIN
associated_table_prefix,
placement,
chunk_size_bytes,
tablespace,
current_database()
)
) AS res;

View File

@ -142,6 +142,7 @@ CREATE TABLE IF NOT EXISTS _iobeamdb_catalog.partition (
epoch_id INT NOT NULL REFERENCES _iobeamdb_catalog.partition_epoch (id) ON DELETE CASCADE,
keyspace_start SMALLINT NOT NULL CHECK (keyspace_start >= 0), --start inclusive
keyspace_end SMALLINT NOT NULL CHECK (keyspace_end > 0), --end inclusive; compatible with between operator
tablespace NAME NULL,
UNIQUE (epoch_id, keyspace_start),
CHECK (keyspace_end > keyspace_start)
);

View File

@ -31,6 +31,7 @@ sql/main/hypertable_replica_triggers.sql
sql/main/field_triggers.sql
sql/main/partitioning.sql
sql/main/schema_info.sql
sql/main/partition_triggers.sql
sql/main/partition_replica_triggers.sql
sql/main/chunk_replica_node_index.sql
sql/main/chunk_replica_node_index_triggers.sql

View File

@ -4,6 +4,7 @@ CREATE OR REPLACE FUNCTION _iobeamdb_internal.on_change_chunk_replica_node()
$BODY$
DECLARE
partition_replica_row _iobeamdb_catalog.partition_replica;
partition _iobeamdb_catalog.partition;
chunk_row _iobeamdb_catalog.chunk;
kind pg_class.relkind%type;
BEGIN
@ -13,6 +14,11 @@ BEGIN
FROM _iobeamdb_catalog.partition_replica AS p
WHERE p.id = NEW.partition_replica_id;
SELECT *
INTO STRICT partition
FROM _iobeamdb_catalog.partition AS p
WHERE p.id = partition_replica_row.partition_id;
SELECT *
INTO STRICT chunk_row
FROM _iobeamdb_catalog.chunk AS c
@ -21,7 +27,8 @@ BEGIN
IF NEW.database_name = current_database() THEN
PERFORM _iobeamdb_internal.create_local_data_table(NEW.schema_name, NEW.table_name,
partition_replica_row.schema_name,
partition_replica_row.table_name);
partition_replica_row.table_name,
partition.tablespace);
PERFORM _iobeamdb_internal.create_chunk_replica_node_index(NEW.schema_name, NEW.table_name,
h.main_schema_name, h.main_index_name, h.definition)

View File

@ -26,16 +26,25 @@ DECLARE
hypertable_row _iobeamdb_catalog.hypertable;
table_name NAME;
schema_name NAME;
tablespace_oid OID;
tablespace_name NAME;
time_column_type REGTYPE;
att_row pg_attribute;
main_table_has_items BOOLEAN;
BEGIN
SELECT relname, nspname
INTO STRICT table_name, schema_name
SELECT relname, nspname, reltablespace
INTO STRICT table_name, schema_name, tablespace_oid
FROM pg_class c
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
WHERE c.OID = main_table;
--tables that don't have an associated tablespace has reltablespace OID set to 0
--in pg_class and there is no matching row in pg_tablespace
SELECT spcname
INTO tablespace_name
FROM pg_tablespace t
WHERE t.OID = tablespace_oid;
BEGIN
SELECT atttypid
INTO STRICT time_column_type
@ -84,7 +93,8 @@ BEGIN
associated_schema_name,
associated_table_prefix,
placement,
chunk_size_bytes
chunk_size_bytes,
tablespace_name
);
EXCEPTION
WHEN unique_violation THEN

View File

@ -0,0 +1,29 @@
CREATE OR REPLACE FUNCTION _iobeamdb_internal.on_change_partition()
RETURNS TRIGGER LANGUAGE PLPGSQL AS
$BODY$
DECLARE
BEGIN
IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
IF NEW.tablespace IS NOT NULL THEN
DECLARE
tablespace_row pg_catalog.pg_tablespace;
BEGIN
SELECT * FROM pg_catalog.pg_tablespace t
INTO tablespace_row
WHERE t.spcname = NEW.tablespace;
IF NOT FOUND THEN
RAISE EXCEPTION 'No tablespace % in database %', NEW.tablespace, current_database()
USING ERRCODE = 'IO501';
END IF;
END;
END IF;
ELSIF TG_OP = 'DELETE' THEN
RETURN OLD;
ELSE
PERFORM _iobeamdb_internal.on_trigger_error(TG_OP, TG_TABLE_SCHEMA, TG_TABLE_NAME);
END IF;
RETURN NEW;
END
$BODY$
SET SEARCH_PATH = 'public';

View File

@ -70,6 +70,11 @@ BEGIN
AFTER INSERT OR UPDATE OR DELETE ON _iobeamdb_catalog.node
FOR EACH ROW EXECUTE PROCEDURE _iobeamdb_internal.on_change_node();
DROP TRIGGER IF EXISTS trigger_main_on_change_partition
ON _iobeamdb_catalog.partition;
CREATE TRIGGER trigger_main_on_change_partition AFTER INSERT OR UPDATE OR DELETE ON _iobeamdb_catalog.partition
FOR EACH ROW EXECUTE PROCEDURE _iobeamdb_internal.on_change_partition();
-- no DELETE: it would be a no-op
DROP TRIGGER IF EXISTS trigger_main_on_change_partition_replica_table
ON _iobeamdb_catalog.partition_replica;

View File

@ -93,16 +93,32 @@ CREATE OR REPLACE FUNCTION _iobeamdb_internal.create_local_data_table(
schema_name NAME,
table_name NAME,
parent_schema_name NAME,
parent_table_name NAME
parent_table_name NAME,
tablespace_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
tablespace_oid pg_catalog.pg_tablespace.oid%type;
tablespace_clause TEXT = '';
BEGIN
SELECT t.oid
INTO tablespace_oid
FROM pg_catalog.pg_tablespace t
WHERE t.spcname = tablespace_name;
IF tablespace_oid IS NOT NULL THEN
tablespace_clause := format('TABLESPACE %s', tablespace_name);
ELSIF tablespace_name IS NOT NULL THEN
RAISE EXCEPTION 'No tablespace % in database %', tablespace_name, current_database()
USING ERRCODE = 'IO501';
END IF;
EXECUTE format(
$$
CREATE TABLE IF NOT EXISTS %1$I.%2$I () INHERITS(%3$I.%4$I);
CREATE TABLE IF NOT EXISTS %1$I.%2$I () INHERITS(%3$I.%4$I) %5$s;
$$,
schema_name, table_name, parent_schema_name, parent_table_name);
schema_name, table_name, parent_schema_name, parent_table_name, tablespace_clause);
END
$BODY$;

View File

@ -76,7 +76,8 @@ CREATE OR REPLACE FUNCTION add_partition_epoch(
keyspace_start SMALLINT [],
partitioning_column NAME,
partitioning_func_schema NAME,
partitioning_func NAME
partitioning_func NAME,
tablespace_name NAME
)
RETURNS VOID LANGUAGE SQL VOLATILE AS
$BODY$
@ -86,12 +87,13 @@ $BODY$
VALUES (hypertable_id, NULL, NULL, partitioning_func_schema, partitioning_func, 32768, partitioning_column)
RETURNING id
)
INSERT INTO _iobeamdb_catalog.partition (epoch_id, keyspace_start, keyspace_end)
INSERT INTO _iobeamdb_catalog.partition (epoch_id, keyspace_start, keyspace_end, tablespace)
SELECT
epoch.id,
lag(start, 1, 0)
OVER (),
start - 1
start - 1,
tablespace_name
FROM unnest(keyspace_start :: INT [] || (32768) :: INT) start, epoch
$BODY$;
@ -100,7 +102,8 @@ CREATE OR REPLACE FUNCTION add_equi_partition_epoch(
number_partitions SMALLINT,
partitioning_column NAME,
partitioning_func_schema NAME,
partitioning_func NAME
partitioning_func NAME,
tablespace_name NAME
)
RETURNS VOID LANGUAGE SQL VOLATILE AS
$BODY$
@ -110,6 +113,7 @@ SELECT add_partition_epoch(
FROM generate_series(1, number_partitions - 1) AS start) :: SMALLINT []),
partitioning_column,
partitioning_func_schema,
partitioning_func
partitioning_func,
tablespace_name
)
$BODY$;

View File

@ -14,6 +14,7 @@ CREATE OR REPLACE FUNCTION _iobeamdb_meta.create_hypertable(
associated_table_prefix NAME,
placement _iobeamdb_catalog.chunk_placement_type,
chunk_size_bytes BIGINT,
tablespace NAME,
created_on NAME
)
RETURNS _iobeamdb_catalog.hypertable LANGUAGE PLPGSQL VOLATILE AS
@ -72,7 +73,8 @@ BEGIN
RETURNING * INTO hypertable_row;
IF number_partitions != 0 THEN
PERFORM add_equi_partition_epoch(hypertable_row.id, number_partitions, partitioning_column, partitioning_func_schema, partitioning_func);
PERFORM add_equi_partition_epoch(hypertable_row.id, number_partitions, partitioning_column,
partitioning_func_schema, partitioning_func, tablespace);
END IF;
RETURN hypertable_row;
END

View File

@ -165,12 +165,12 @@ FROM _iobeamdb_catalog.partition_epoch;
SELECT *
FROM _iobeamdb_catalog.partition;
id | epoch_id | keyspace_start | keyspace_end
----+----------+----------------+--------------
1 | 1 | 0 | 16383
2 | 1 | 16384 | 32767
3 | 2 | 0 | 16383
4 | 2 | 16384 | 32767
id | epoch_id | keyspace_start | keyspace_end | tablespace
----+----------+----------------+--------------+------------
1 | 1 | 0 | 16383 |
2 | 1 | 16384 | 32767 |
3 | 2 | 0 | 16383 |
4 | 2 | 16384 | 32767 |
(4 rows)
SELECT *
@ -275,12 +275,12 @@ FROM _iobeamdb_catalog.partition_epoch;
SELECT *
FROM _iobeamdb_catalog.partition;
id | epoch_id | keyspace_start | keyspace_end
----+----------+----------------+--------------
1 | 1 | 0 | 16383
2 | 1 | 16384 | 32767
3 | 2 | 0 | 16383
4 | 2 | 16384 | 32767
id | epoch_id | keyspace_start | keyspace_end | tablespace
----+----------+----------------+--------------+------------
1 | 1 | 0 | 16383 |
2 | 1 | 16384 | 32767 |
3 | 2 | 0 | 16383 |
4 | 2 | 16384 | 32767 |
(4 rows)
SELECT *

View File

@ -0,0 +1,152 @@
psql:include/create_clustered_db.sql:12: NOTICE: 00000: installing required extension "dblink"
LOCATION: CreateExtensionInternal, extension.c:1441
psql:include/create_clustered_db.sql:12: NOTICE: 00000: installing required extension "postgres_fdw"
LOCATION: CreateExtensionInternal, extension.c:1441
psql:include/create_clustered_db.sql:12: NOTICE: 00000: installing required extension "hstore"
LOCATION: CreateExtensionInternal, extension.c:1441
setup_meta
------------
(1 row)
psql:include/create_clustered_db.sql:17: NOTICE: 00000: installing required extension "dblink"
LOCATION: CreateExtensionInternal, extension.c:1441
psql:include/create_clustered_db.sql:17: NOTICE: 00000: installing required extension "postgres_fdw"
LOCATION: CreateExtensionInternal, extension.c:1441
psql:include/create_clustered_db.sql:17: NOTICE: 00000: installing required extension "hstore"
LOCATION: CreateExtensionInternal, extension.c:1441
setup_main
------------
(1 row)
psql:include/create_clustered_db.sql:23: NOTICE: 00000: installing required extension "dblink"
LOCATION: CreateExtensionInternal, extension.c:1441
psql:include/create_clustered_db.sql:23: NOTICE: 00000: installing required extension "postgres_fdw"
LOCATION: CreateExtensionInternal, extension.c:1441
psql:include/create_clustered_db.sql:23: NOTICE: 00000: installing required extension "hstore"
LOCATION: CreateExtensionInternal, extension.c:1441
setup_main
------------
(1 row)
\c meta
SELECT add_cluster_user('postgres', NULL);
add_cluster_user
------------------
(1 row)
SELECT set_meta('meta' :: NAME, 'localhost');
set_meta
----------
(1 row)
SELECT add_node('Test1' :: NAME, 'localhost');
add_node
----------
(1 row)
SELECT add_node('test2' :: NAME, 'localhost');
add_node
----------
(1 row)
\c Test1
--test hypertable with tables space
create tablespace tspace1 location '/var/lib/postgresql/data/tests/tspace1';
create table test_tspace(time timestamp, temp float, device_id text) tablespace tspace1;
select create_hypertable('test_tspace', 'time', 'device_id');
create_hypertable
-------------------
(1 row)
select * from _iobeamdb_catalog.partition p INNER JOIN _iobeamdb_catalog.partition_replica pr ON (pr.partition_id = p.id);
id | epoch_id | keyspace_start | keyspace_end | tablespace | id | partition_id | hypertable_id | replica_id | schema_name | table_name
----+----------+----------------+--------------+------------+----+--------------+---------------+------------+--------------------+------------------------
1 | 1 | 0 | 16383 | tspace1 | 1 | 1 | 1 | 0 | _iobeamdb_internal | _hyper_1_1_0_partition
2 | 1 | 16384 | 32767 | tspace1 | 2 | 2 | 1 | 0 | _iobeamdb_internal | _hyper_1_2_0_partition
(2 rows)
insert into test_tspace values ('2017-01-20T09:00:01', 24.3, 'dev1');
insert into test_tspace values ('2017-01-20T09:00:02', 22.3, 'dev7');
\dt test_tspace
List of relations
Schema | Name | Type | Owner
---------+-------------+-------+----------
io_test | test_tspace | table | postgres
(1 row)
--verify that the table chunk has the correct tablespace
\d+ _iobeamdb_internal.*
Table "_iobeamdb_internal._hyper_1_0_replica"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------------+-----------+----------+--------------+-------------
time | timestamp without time zone | | plain | |
temp | double precision | | plain | |
device_id | text | | extended | |
Inherits: _iobeamdb_internal._hyper_1_root
Child tables: _iobeamdb_internal._hyper_1_1_0_partition,
_iobeamdb_internal._hyper_1_2_0_partition
Foreign table "_iobeamdb_internal._hyper_1_1_0_1_data"
Column | Type | Modifiers | FDW Options | Storage | Stats target | Description
-----------+-----------------------------+-----------+-------------+----------+--------------+-------------
time | timestamp without time zone | | | plain | |
temp | double precision | | | plain | |
device_id | text | | | extended | |
Check constraints:
"partition" CHECK (_iobeamdb_catalog.get_partition_for_key(device_id, 32768) >= '0'::smallint AND _iobeamdb_catalog.get_partition_for_key(device_id, 32768) <= '16383'::smallint)
Server: test2
FDW Options: (schema_name '_iobeamdb_internal', table_name '_hyper_1_1_0_1_data')
Inherits: _iobeamdb_internal._hyper_1_1_0_partition
Table "_iobeamdb_internal._hyper_1_1_0_partition"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------------+-----------+----------+--------------+-------------
time | timestamp without time zone | | plain | |
temp | double precision | | plain | |
device_id | text | | extended | |
Check constraints:
"partition" CHECK (_iobeamdb_catalog.get_partition_for_key(device_id, 32768) >= '0'::smallint AND _iobeamdb_catalog.get_partition_for_key(device_id, 32768) <= '16383'::smallint)
Inherits: _iobeamdb_internal._hyper_1_0_replica
Child tables: _iobeamdb_internal._hyper_1_1_0_1_data
Table "_iobeamdb_internal._hyper_1_2_0_2_data"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------------+-----------+----------+--------------+-------------
time | timestamp without time zone | | plain | |
temp | double precision | | plain | |
device_id | text | | extended | |
Check constraints:
"partition" CHECK (_iobeamdb_catalog.get_partition_for_key(device_id, 32768) >= '16384'::smallint AND _iobeamdb_catalog.get_partition_for_key(device_id, 32768) <= '32767'::smallint)
Inherits: _iobeamdb_internal._hyper_1_2_0_partition
Tablespace: "tspace1"
Table "_iobeamdb_internal._hyper_1_2_0_partition"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------------+-----------+----------+--------------+-------------
time | timestamp without time zone | | plain | |
temp | double precision | | plain | |
device_id | text | | extended | |
Check constraints:
"partition" CHECK (_iobeamdb_catalog.get_partition_for_key(device_id, 32768) >= '16384'::smallint AND _iobeamdb_catalog.get_partition_for_key(device_id, 32768) <= '32767'::smallint)
Inherits: _iobeamdb_internal._hyper_1_0_replica
Child tables: _iobeamdb_internal._hyper_1_2_0_2_data
Table "_iobeamdb_internal._hyper_1_root"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+-----------------------------+-----------+----------+--------------+-------------
time | timestamp without time zone | | plain | |
temp | double precision | | plain | |
device_id | text | | extended | |
Child tables: _iobeamdb_internal._hyper_1_0_replica
--cleanup
drop table test_tspace;
drop tablespace tspace1;

View File

@ -0,0 +1,32 @@
\set ON_ERROR_STOP 1
\set VERBOSITY verbose
\set SHOW_CONTEXT never
\ir include/create_clustered_db.sql
\set ECHO ALL
\c meta
SELECT add_cluster_user('postgres', NULL);
SELECT set_meta('meta' :: NAME, 'localhost');
SELECT add_node('Test1' :: NAME, 'localhost');
SELECT add_node('test2' :: NAME, 'localhost');
\c Test1
--test hypertable with tables space
create tablespace tspace1 location '/var/lib/postgresql/data/tests/tspace1';
create table test_tspace(time timestamp, temp float, device_id text) tablespace tspace1;
select create_hypertable('test_tspace', 'time', 'device_id');
select * from _iobeamdb_catalog.partition p INNER JOIN _iobeamdb_catalog.partition_replica pr ON (pr.partition_id = p.id);
insert into test_tspace values ('2017-01-20T09:00:01', 24.3, 'dev1');
insert into test_tspace values ('2017-01-20T09:00:02', 22.3, 'dev7');
\dt test_tspace
--verify that the table chunk has the correct tablespace
\d+ _iobeamdb_internal.*
--cleanup
drop table test_tspace;
drop tablespace tspace1;

View File

@ -108,13 +108,12 @@ iobeamdb_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
if (IobeamLoaded())
{
change_table_name_context context;
char* printParse = GetConfigOptionByName("io.print_parse", NULL, true);
/* set to false to not print all internal actions */
SetConfigOption("io.print_parse", "false", PGC_USERSET, PGC_S_SESSION);
/* replace call to main table with call to the replica table */
change_table_name_context context;
context.hypertable_info = NIL;
change_table_name_walker((Node *) parse, &context);
if (list_length(context.hypertable_info) > 0)

View File

@ -7,6 +7,7 @@ fi
DOCKER_HOST=${DOCKER_HOST:-localhost}
CONTAINER_NAME=${CONTAINER_NAME:-iobeamdb}
DATA_DIR=${DATA_DIR-$PWD/data}
BIN_CMD=${BIN_CMD:-postgres}
VOLUME_MOUNT=""
if [[ -n "$DATA_DIR" ]]; then
@ -17,7 +18,7 @@ docker run -d \
-p 5432:5432 \
-m 4g \
-e PGDATA=/var/lib/postgresql/data/iobeam \
$IMAGE_NAME postgres \
$IMAGE_NAME $BIN_CMD \
-csynchronous_commit=off -cwal_writer_delay=1000 \
-cmax_locks_per_transaction=1000 \
-cshared_preload_libraries=pg_stat_statements,dblink,iobeamdb \

View File

@ -11,7 +11,7 @@ select setup_main();
SELECT add_cluster_user('postgres', NULL);
\echo 'Adding database to the single-node cluster...'
\echo 'Adding database iobeam to the single-node cluster...'
SELECT set_meta('iobeam' :: NAME, 'localhost');
SELECT add_node('iobeam' :: NAME, 'localhost');

View File

@ -16,4 +16,13 @@ if [[ -n $matching ]]; then
docker rm $matching
fi
CONTAINER_NAME=$CONTAINER_NAME DATA_DIR="" IMAGE_NAME=$IMAGE_NAME $(dirname $0)/docker-run.sh
CONTAINER_NAME=$CONTAINER_NAME \
DATA_DIR="" \
IMAGE_NAME=$IMAGE_NAME \
$(dirname $0)/docker-run.sh
# Create data directories for tablespaces tests
docker exec -i $CONTAINER_NAME /bin/bash << 'EOF'
mkdir -p /var/lib/postgresql/data/tests/tspace{1,2}
chown postgres:postgres /var/lib/postgresql/data/tests/tspace{1,2}
EOF