mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 02:53:51 +08:00
Spread chunk indexes across tablespaces like chunks
Currently, chunk indexes are always created in the tablespace of the index on the main table (which could be none/default one), even if the chunks themselves are created in different tablespaces. This is problematic in a multi-disk setting where each disk is a separate tablespace where chunks are placed. The chunk indexes might exhaust the space on the common (often default tablespace) which might not have a lot of disk space. This also prohibits the database, including index storage to grow by adding new tablespaces. Instead, chunk indexes are now created in the "next" tablespace after that of their chunks to both spread indexes across tablespaces and avoid colocating indexes with their chunks (for I/O throughput reasons). To optionally avoid this spreading, one can pin chunk indexes to a specific tablespace by setting an explicit tablespace on a main table index.
This commit is contained in:
parent
e85721a8ed
commit
d135256ed7
@ -400,7 +400,7 @@ chunk_create_table(Chunk *chunk, Hypertable *ht)
|
|||||||
.type = T_CreateStmt,
|
.type = T_CreateStmt,
|
||||||
.relation = makeRangeVar(NameStr(chunk->fd.schema_name), NameStr(chunk->fd.table_name), 0),
|
.relation = makeRangeVar(NameStr(chunk->fd.schema_name), NameStr(chunk->fd.table_name), 0),
|
||||||
.inhRelations = list_make1(makeRangeVar(NameStr(ht->fd.schema_name), NameStr(ht->fd.table_name), 0)),
|
.inhRelations = list_make1(makeRangeVar(NameStr(ht->fd.schema_name), NameStr(ht->fd.table_name), 0)),
|
||||||
.tablespacename = hypertable_select_tablespace(ht, chunk),
|
.tablespacename = hypertable_select_tablespace_name(ht, chunk),
|
||||||
.options = get_reloptions(ht->main_table_relid),
|
.options = get_reloptions(ht->main_table_relid),
|
||||||
};
|
};
|
||||||
Oid uid,
|
Oid uid,
|
||||||
|
@ -195,6 +195,35 @@ chunk_adjust_attnos(IndexInfo *ii, Relation htrel, Relation idxrel, Relation chu
|
|||||||
chunk_adjust_expr_attnos(ii, htrel, idxrel, chunkrel);
|
chunk_adjust_expr_attnos(ii, htrel, idxrel, chunkrel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHUNK_INDEX_TABLESPACE_OFFSET 1
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pick a chunk index's tablespace at an offset from the chunk's tablespace in
|
||||||
|
* order to avoid colocating chunks and their indexes in the same tablespace.
|
||||||
|
* This hopefully leads to more I/O parallelism.
|
||||||
|
*/
|
||||||
|
static Oid
|
||||||
|
chunk_index_select_tablespace(Relation htrel, Relation chunkrel)
|
||||||
|
{
|
||||||
|
Cache *hcache = hypertable_cache_pin();
|
||||||
|
Hypertable *ht = hypertable_cache_get_entry(hcache, htrel->rd_id);
|
||||||
|
Tablespace *tspc;
|
||||||
|
Oid tablespace_oid = InvalidOid;
|
||||||
|
|
||||||
|
Assert(ht != NULL);
|
||||||
|
|
||||||
|
tspc = hypertable_get_tablespace_at_offset_from(ht, chunkrel->rd_rel->reltablespace,
|
||||||
|
CHUNK_INDEX_TABLESPACE_OFFSET);
|
||||||
|
|
||||||
|
if (NULL != tspc)
|
||||||
|
tablespace_oid = tspc->tablespace_oid;
|
||||||
|
|
||||||
|
cache_release(hcache);
|
||||||
|
|
||||||
|
return tablespace_oid;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a chunk index based on the configuration of the "parent" index.
|
* Create a chunk index based on the configuration of the "parent" index.
|
||||||
*/
|
*/
|
||||||
@ -213,6 +242,7 @@ chunk_relation_index_create(Relation htrel,
|
|||||||
Datum indclass;
|
Datum indclass;
|
||||||
oidvector *indclassoid;
|
oidvector *indclassoid;
|
||||||
List *colnames = create_index_colnames(template_indexrel);
|
List *colnames = create_index_colnames(template_indexrel);
|
||||||
|
Oid tablespace = InvalidOid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the IndexInfo's attnos to match the chunk instead of the
|
* Convert the IndexInfo's attnos to match the chunk instead of the
|
||||||
@ -239,6 +269,15 @@ chunk_relation_index_create(Relation htrel,
|
|||||||
get_rel_name(RelationGetRelid(template_indexrel)),
|
get_rel_name(RelationGetRelid(template_indexrel)),
|
||||||
get_rel_namespace(RelationGetRelid(chunkrel)));
|
get_rel_namespace(RelationGetRelid(chunkrel)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the index's tablespace. Use the main index's tablespace, or,
|
||||||
|
* if not set, select one at an offset from the chunk's tablespace.
|
||||||
|
*/
|
||||||
|
if (OidIsValid(template_indexrel->rd_rel->reltablespace))
|
||||||
|
tablespace = template_indexrel->rd_rel->reltablespace;
|
||||||
|
else
|
||||||
|
tablespace = chunk_index_select_tablespace(htrel, chunkrel);
|
||||||
|
|
||||||
chunk_indexrelid = index_create(chunkrel,
|
chunk_indexrelid = index_create(chunkrel,
|
||||||
indexname,
|
indexname,
|
||||||
InvalidOid,
|
InvalidOid,
|
||||||
@ -246,7 +285,7 @@ chunk_relation_index_create(Relation htrel,
|
|||||||
indexinfo,
|
indexinfo,
|
||||||
colnames,
|
colnames,
|
||||||
template_indexrel->rd_rel->relam,
|
template_indexrel->rd_rel->relam,
|
||||||
template_indexrel->rd_rel->reltablespace,
|
tablespace,
|
||||||
template_indexrel->rd_indcollation,
|
template_indexrel->rd_indcollation,
|
||||||
indclassoid->values,
|
indclassoid->values,
|
||||||
template_indexrel->rd_indoption,
|
template_indexrel->rd_indoption,
|
||||||
|
@ -282,7 +282,7 @@ hypertable_has_tablespace(Hypertable *ht, Oid tspc_oid)
|
|||||||
* chunks in the same closed (space) dimension. This ensures chunks in the same
|
* chunks in the same closed (space) dimension. This ensures chunks in the same
|
||||||
* "space" partition will live on the same disk.
|
* "space" partition will live on the same disk.
|
||||||
*/
|
*/
|
||||||
char *
|
Tablespace *
|
||||||
hypertable_select_tablespace(Hypertable *ht, Chunk *chunk)
|
hypertable_select_tablespace(Hypertable *ht, Chunk *chunk)
|
||||||
{
|
{
|
||||||
Dimension *dim;
|
Dimension *dim;
|
||||||
@ -318,7 +318,39 @@ hypertable_select_tablespace(Hypertable *ht, Chunk *chunk)
|
|||||||
Assert(i >= 0);
|
Assert(i >= 0);
|
||||||
|
|
||||||
/* Use the index of the slice to find the tablespace */
|
/* Use the index of the slice to find the tablespace */
|
||||||
return NameStr(tspcs->tablespaces[i % tspcs->num_tablespaces].fd.tablespace_name);
|
return &tspcs->tablespaces[i % tspcs->num_tablespaces];
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
hypertable_select_tablespace_name(Hypertable *ht, Chunk *chunk)
|
||||||
|
{
|
||||||
|
Tablespace *tspc = hypertable_select_tablespace(ht, chunk);
|
||||||
|
|
||||||
|
if (NULL == tspc)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return NameStr(tspc->fd.tablespace_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the tablespace at an offset from the given tablespace.
|
||||||
|
*/
|
||||||
|
Tablespace *
|
||||||
|
hypertable_get_tablespace_at_offset_from(Hypertable *ht, Oid tablespace_oid, int16 offset)
|
||||||
|
{
|
||||||
|
Tablespaces *tspcs = tablespace_scan(ht->fd.id);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (NULL == tspcs || tspcs->num_tablespaces == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < tspcs->num_tablespaces; i++)
|
||||||
|
{
|
||||||
|
if (tablespace_oid == tspcs->tablespaces[i].tablespace_oid)
|
||||||
|
return &tspcs->tablespaces[(i + offset) % tspcs->num_tablespaces];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Oid
|
static inline Oid
|
||||||
|
@ -30,6 +30,8 @@ extern Chunk *hypertable_get_chunk(Hypertable *h, Point *point);
|
|||||||
extern Oid hypertable_relid(RangeVar *rv);
|
extern Oid hypertable_relid(RangeVar *rv);
|
||||||
extern bool is_hypertable(Oid relid);
|
extern bool is_hypertable(Oid relid);
|
||||||
extern bool hypertable_has_tablespace(Hypertable *ht, Oid tspc_oid);
|
extern bool hypertable_has_tablespace(Hypertable *ht, Oid tspc_oid);
|
||||||
extern char *hypertable_select_tablespace(Hypertable *ht, Chunk *chunk);
|
extern Tablespace *hypertable_select_tablespace(Hypertable *ht, Chunk *chunk);
|
||||||
|
extern char *hypertable_select_tablespace_name(Hypertable *ht, Chunk *chunk);
|
||||||
|
extern Tablespace *hypertable_get_tablespace_at_offset_from(Hypertable *ht, Oid tablespace_oid, int16 offset);
|
||||||
|
|
||||||
#endif /* TIMESCALEDB_HYPERTABLE_H */
|
#endif /* TIMESCALEDB_HYPERTABLE_H */
|
||||||
|
@ -318,15 +318,15 @@ SET timezone = '+1';
|
|||||||
INSERT INTO PUBLIC.drop_chunk_test_ts VALUES(now()-INTERVAL '5 minutes', 1.0, 'dev1');
|
INSERT INTO PUBLIC.drop_chunk_test_ts VALUES(now()-INTERVAL '5 minutes', 1.0, 'dev1');
|
||||||
INSERT INTO PUBLIC.drop_chunk_test_tstz VALUES(now()-INTERVAL '5 minutes', 1.0, 'dev1');
|
INSERT INTO PUBLIC.drop_chunk_test_tstz VALUES(now()-INTERVAL '5 minutes', 1.0, 'dev1');
|
||||||
SELECT * FROM test.show_subtables('drop_chunk_test_ts');
|
SELECT * FROM test.show_subtables('drop_chunk_test_ts');
|
||||||
Child
|
Child | Tablespace
|
||||||
-----------------------------------------
|
-----------------------------------------+------------
|
||||||
_timescaledb_internal._hyper_4_19_chunk
|
_timescaledb_internal._hyper_4_19_chunk |
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('drop_chunk_test_tstz');
|
SELECT * FROM test.show_subtables('drop_chunk_test_tstz');
|
||||||
Child
|
Child | Tablespace
|
||||||
-----------------------------------------
|
-----------------------------------------+------------
|
||||||
_timescaledb_internal._hyper_5_20_chunk
|
_timescaledb_internal._hyper_5_20_chunk |
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
@ -337,8 +337,8 @@ BEGIN;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('drop_chunk_test_ts');
|
SELECT * FROM test.show_subtables('drop_chunk_test_ts');
|
||||||
Child
|
Child | Tablespace
|
||||||
-------
|
-------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT drop_chunks(interval '1 minute', 'drop_chunk_test_tstz');
|
SELECT drop_chunks(interval '1 minute', 'drop_chunk_test_tstz');
|
||||||
@ -348,8 +348,8 @@ BEGIN;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('drop_chunk_test_tstz');
|
SELECT * FROM test.show_subtables('drop_chunk_test_tstz');
|
||||||
Child
|
Child | Tablespace
|
||||||
-------
|
-------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
@ -361,8 +361,8 @@ BEGIN;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('drop_chunk_test_ts');
|
SELECT * FROM test.show_subtables('drop_chunk_test_ts');
|
||||||
Child
|
Child | Tablespace
|
||||||
-------
|
-------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT drop_chunks(now()-interval '1 minute', 'drop_chunk_test_tstz');
|
SELECT drop_chunks(now()-interval '1 minute', 'drop_chunk_test_tstz');
|
||||||
@ -372,8 +372,8 @@ BEGIN;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('drop_chunk_test_tstz');
|
SELECT * FROM test.show_subtables('drop_chunk_test_tstz');
|
||||||
Child
|
Child | Tablespace
|
||||||
-------
|
-------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
@ -405,8 +405,8 @@ BEGIN;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('drop_chunk_test_date');
|
SELECT * FROM test.show_subtables('drop_chunk_test_date');
|
||||||
Child
|
Child | Tablespace
|
||||||
-------
|
-------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
@ -418,8 +418,8 @@ BEGIN;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('drop_chunk_test_date');
|
SELECT * FROM test.show_subtables('drop_chunk_test_date');
|
||||||
Child
|
Child | Tablespace
|
||||||
-------
|
-------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
@ -398,7 +398,7 @@ SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk');
|
|||||||
----------------------------------------+-------------------------------------------------------------------+--------------------+--------+---------+-----------+-------------
|
----------------------------------------+-------------------------------------------------------------------+--------------------+--------+---------+-----------+-------------
|
||||||
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_idx | {time,temp,device} | f | f | f | tablespace1
|
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_device_idx | {time,temp,device} | f | f | f | tablespace2
|
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_device_idx | {time,temp,device} | f | f | f | tablespace2
|
||||||
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_device_idx | {time,temp,device} | f | f | f |
|
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_device_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
-- Creating a new index should propagate to existing chunks, including
|
-- Creating a new index should propagate to existing chunks, including
|
||||||
@ -418,7 +418,7 @@ SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk');
|
|||||||
----------------------------------------+-------------------------------------------------------------------+--------------------+--------+---------+-----------+-------------
|
----------------------------------------+-------------------------------------------------------------------+--------------------+--------+---------+-----------+-------------
|
||||||
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_idx | {time,temp,device} | f | f | f | tablespace1
|
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_device_idx | {time,temp,device} | f | f | f | tablespace2
|
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_device_idx | {time,temp,device} | f | f | f | tablespace2
|
||||||
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_device_idx | {time,temp,device} | f | f | f |
|
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_device_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_time_temp_idx | {time,temp,device} | f | f | f | tablespace2
|
_timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_time_temp_idx | {time,temp,device} | f | f | f | tablespace2
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
|
@ -21,13 +21,13 @@ SELECT * FROM test.show_columns('reindex_test');
|
|||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('reindex_test');
|
SELECT * FROM test.show_subtables('reindex_test');
|
||||||
Child
|
Child | Tablespace
|
||||||
----------------------------------------
|
----------------------------------------+------------
|
||||||
_timescaledb_internal._hyper_1_1_chunk
|
_timescaledb_internal._hyper_1_1_chunk |
|
||||||
_timescaledb_internal._hyper_1_2_chunk
|
_timescaledb_internal._hyper_1_2_chunk |
|
||||||
_timescaledb_internal._hyper_1_3_chunk
|
_timescaledb_internal._hyper_1_3_chunk |
|
||||||
_timescaledb_internal._hyper_1_4_chunk
|
_timescaledb_internal._hyper_1_4_chunk |
|
||||||
_timescaledb_internal._hyper_1_5_chunk
|
_timescaledb_internal._hyper_1_5_chunk |
|
||||||
(5 rows)
|
(5 rows)
|
||||||
|
|
||||||
-- show reindexing
|
-- show reindexing
|
||||||
|
@ -122,10 +122,10 @@ INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 1, 22.5);
|
|||||||
INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 2, 22.5);
|
INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 2, 22.5);
|
||||||
--check that there are two chunks
|
--check that there are two chunks
|
||||||
SELECT * FROM test.show_subtables('int_part');
|
SELECT * FROM test.show_subtables('int_part');
|
||||||
Child
|
Child | Tablespace
|
||||||
----------------------------------------
|
----------------------------------------+------------
|
||||||
_timescaledb_internal._hyper_2_5_chunk
|
_timescaledb_internal._hyper_2_5_chunk |
|
||||||
_timescaledb_internal._hyper_2_6_chunk
|
_timescaledb_internal._hyper_2_6_chunk |
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
SELECT * FROM "int_part" WHERE object_id = 1;
|
SELECT * FROM "int_part" WHERE object_id = 1;
|
||||||
|
@ -77,25 +77,33 @@ SELECT * FROM show_tablespaces('tspace_2dim');
|
|||||||
|
|
||||||
--insert into another chunk
|
--insert into another chunk
|
||||||
INSERT INTO tspace_2dim VALUES ('2017-01-20T09:00:01', 24.3, 'brown');
|
INSERT INTO tspace_2dim VALUES ('2017-01-20T09:00:01', 24.3, 'brown');
|
||||||
SELECT relname, spcname FROM pg_class c
|
SELECT * FROM test.show_subtables('tspace_2dim');
|
||||||
INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid)
|
Child | Tablespace
|
||||||
INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname);
|
----------------------------------------+-------------
|
||||||
relname | spcname
|
_timescaledb_internal._hyper_1_1_chunk | tablespace1
|
||||||
------------------+-------------
|
_timescaledb_internal._hyper_1_2_chunk | tablespace2
|
||||||
_hyper_1_1_chunk | tablespace1
|
|
||||||
_hyper_1_2_chunk | tablespace2
|
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
--indexes should inherit the tablespace of their chunk
|
||||||
|
SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk');
|
||||||
|
Table | Index | Columns | Unique | Primary | Exclusion | Tablespace
|
||||||
|
----------------------------------------+--------------------------------------------------------------------+--------------------+--------+---------+-----------+-------------
|
||||||
|
_timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_tspace_2dim_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
_timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_tspace_2dim_device_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
_timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_tspace_2dim_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
_timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_tspace_2dim_device_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
--
|
--
|
||||||
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
|
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
|
||||||
-- User doesn't have permission on tablespace1 --> error
|
-- User doesn't have permission on tablespace1 --> error
|
||||||
CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1;
|
CREATE TABLE tspace_1dim(time timestamp, temp float, device text);
|
||||||
ERROR: permission denied for tablespace tablespace1
|
|
||||||
-- Grant permission to tablespace1
|
-- Grant permission to tablespace1
|
||||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||||
GRANT CREATE ON TABLESPACE tablespace1 TO :ROLE_DEFAULT_PERM_USER_2;
|
GRANT CREATE ON TABLESPACE tablespace1 TO :ROLE_DEFAULT_PERM_USER_2;
|
||||||
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
|
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
|
||||||
CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1;
|
CREATE TABLE tspace_1dim(time timestamp, temp float, device text);
|
||||||
|
ERROR: relation "tspace_1dim" already exists
|
||||||
SELECT create_hypertable('tspace_1dim', 'time');
|
SELECT create_hypertable('tspace_1dim', 'time');
|
||||||
NOTICE: Adding NOT NULL constraint to time column time (NULL time values not allowed)
|
NOTICE: Adding NOT NULL constraint to time column time (NULL time values not allowed)
|
||||||
create_hypertable
|
create_hypertable
|
||||||
@ -103,6 +111,12 @@ NOTICE: Adding NOT NULL constraint to time column time (NULL time values not al
|
|||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT attach_tablespace('tablespace1', 'tspace_1dim');
|
||||||
|
attach_tablespace
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT attach_tablespace('tablespace2', 'tspace_1dim');
|
SELECT attach_tablespace('tablespace2', 'tspace_1dim');
|
||||||
attach_tablespace
|
attach_tablespace
|
||||||
-------------------
|
-------------------
|
||||||
@ -120,17 +134,33 @@ SELECT * FROM _timescaledb_catalog.tablespace;
|
|||||||
|
|
||||||
INSERT INTO tspace_1dim VALUES ('2017-01-20T09:00:01', 24.3, 'blue');
|
INSERT INTO tspace_1dim VALUES ('2017-01-20T09:00:01', 24.3, 'blue');
|
||||||
INSERT INTO tspace_1dim VALUES ('2017-03-20T09:00:01', 24.3, 'brown');
|
INSERT INTO tspace_1dim VALUES ('2017-03-20T09:00:01', 24.3, 'brown');
|
||||||
SELECT relname, spcname FROM pg_class c
|
SELECT * FROM test.show_subtablesp('tspace_%');
|
||||||
INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid)
|
Parent | Child | Tablespace
|
||||||
INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname);
|
-------------+----------------------------------------+-------------
|
||||||
relname | spcname
|
tspace_2dim | _timescaledb_internal._hyper_1_1_chunk | tablespace1
|
||||||
------------------+-------------
|
tspace_2dim | _timescaledb_internal._hyper_1_2_chunk | tablespace2
|
||||||
_hyper_1_1_chunk | tablespace1
|
tspace_1dim | _timescaledb_internal._hyper_2_3_chunk | tablespace1
|
||||||
_hyper_1_2_chunk | tablespace2
|
tspace_1dim | _timescaledb_internal._hyper_2_4_chunk | tablespace2
|
||||||
_hyper_2_3_chunk | tablespace1
|
|
||||||
_hyper_2_4_chunk | tablespace2
|
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
|
--indexes should inherit the tablespace of their chunk, unless the
|
||||||
|
--parent index has a tablespace set, in which case the chunks'
|
||||||
|
--corresponding indexes are pinned to the parent index's
|
||||||
|
--tablespace. The parent index can have a tablespace set in two cases:
|
||||||
|
--(1) if explicitly set in CREATE INDEX, or (2) if the main table was
|
||||||
|
--created with a tablespace, because then default indexes will be
|
||||||
|
--created in that tablespace too.
|
||||||
|
SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk');
|
||||||
|
Table | Index | Columns | Unique | Primary | Exclusion | Tablespace
|
||||||
|
----------------------------------------+--------------------------------------------------------------------+--------------------+--------+---------+-----------+-------------
|
||||||
|
_timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_tspace_2dim_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
_timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_tspace_2dim_device_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
_timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_tspace_2dim_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
_timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_tspace_2dim_device_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
_timescaledb_internal._hyper_2_3_chunk | _timescaledb_internal._hyper_2_3_chunk_tspace_1dim_time_idx | {time,temp,device} | f | f | f | tablespace2
|
||||||
|
_timescaledb_internal._hyper_2_4_chunk | _timescaledb_internal._hyper_2_4_chunk_tspace_1dim_time_idx | {time,temp,device} | f | f | f | tablespace1
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
--detach tablespace1 from all tables. Due to lack of permissions,
|
--detach tablespace1 from all tables. Due to lack of permissions,
|
||||||
--should only detach from 'tspace_1dim' (1 tablespace)
|
--should only detach from 'tspace_1dim' (1 tablespace)
|
||||||
SELECT detach_tablespace('tablespace1');
|
SELECT detach_tablespace('tablespace1');
|
||||||
|
@ -45,12 +45,12 @@ SELECT * FROM _timescaledb_catalog.chunk;
|
|||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
SELECT * FROM test.show_subtables('"two_Partitions"');
|
SELECT * FROM test.show_subtables('"two_Partitions"');
|
||||||
Child
|
Child | Tablespace
|
||||||
----------------------------------------
|
----------------------------------------+------------
|
||||||
_timescaledb_internal._hyper_1_1_chunk
|
_timescaledb_internal._hyper_1_1_chunk |
|
||||||
_timescaledb_internal._hyper_1_2_chunk
|
_timescaledb_internal._hyper_1_2_chunk |
|
||||||
_timescaledb_internal._hyper_1_3_chunk
|
_timescaledb_internal._hyper_1_3_chunk |
|
||||||
_timescaledb_internal._hyper_1_4_chunk
|
_timescaledb_internal._hyper_1_4_chunk |
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
SELECT * FROM "two_Partitions";
|
SELECT * FROM "two_Partitions";
|
||||||
@ -85,8 +85,8 @@ SELECT * FROM _timescaledb_catalog.chunk;
|
|||||||
|
|
||||||
-- should be empty
|
-- should be empty
|
||||||
SELECT * FROM test.show_subtables('"two_Partitions"');
|
SELECT * FROM test.show_subtables('"two_Partitions"');
|
||||||
Child
|
Child | Tablespace
|
||||||
-------
|
-------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT * FROM "two_Partitions";
|
SELECT * FROM "two_Partitions";
|
||||||
@ -140,8 +140,8 @@ WARNING: FIRING trigger when: BEFORE level: STATEMENT op: TRUNCATE cnt: <NULL>
|
|||||||
WARNING: FIRING trigger when: AFTER level: STATEMENT op: TRUNCATE cnt: <NULL> trigger_name _test_truncate_after
|
WARNING: FIRING trigger when: AFTER level: STATEMENT op: TRUNCATE cnt: <NULL> trigger_name _test_truncate_after
|
||||||
-- should be empty
|
-- should be empty
|
||||||
SELECT * FROM test.show_subtables('"two_Partitions"');
|
SELECT * FROM test.show_subtables('"two_Partitions"');
|
||||||
Child
|
Child | Tablespace
|
||||||
-------
|
-------+------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
SELECT * FROM "two_Partitions";
|
SELECT * FROM "two_Partitions";
|
||||||
|
@ -57,22 +57,24 @@ SELECT * FROM show_tablespaces('tspace_2dim');
|
|||||||
--insert into another chunk
|
--insert into another chunk
|
||||||
INSERT INTO tspace_2dim VALUES ('2017-01-20T09:00:01', 24.3, 'brown');
|
INSERT INTO tspace_2dim VALUES ('2017-01-20T09:00:01', 24.3, 'brown');
|
||||||
|
|
||||||
SELECT relname, spcname FROM pg_class c
|
SELECT * FROM test.show_subtables('tspace_2dim');
|
||||||
INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid)
|
|
||||||
INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname);
|
--indexes should inherit the tablespace of their chunk
|
||||||
|
SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk');
|
||||||
|
|
||||||
--
|
--
|
||||||
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
|
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
|
||||||
-- User doesn't have permission on tablespace1 --> error
|
-- User doesn't have permission on tablespace1 --> error
|
||||||
CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1;
|
CREATE TABLE tspace_1dim(time timestamp, temp float, device text);
|
||||||
|
|
||||||
-- Grant permission to tablespace1
|
-- Grant permission to tablespace1
|
||||||
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
||||||
GRANT CREATE ON TABLESPACE tablespace1 TO :ROLE_DEFAULT_PERM_USER_2;
|
GRANT CREATE ON TABLESPACE tablespace1 TO :ROLE_DEFAULT_PERM_USER_2;
|
||||||
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
|
SET ROLE :ROLE_DEFAULT_PERM_USER_2;
|
||||||
CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1;
|
CREATE TABLE tspace_1dim(time timestamp, temp float, device text);
|
||||||
|
|
||||||
SELECT create_hypertable('tspace_1dim', 'time');
|
SELECT create_hypertable('tspace_1dim', 'time');
|
||||||
|
SELECT attach_tablespace('tablespace1', 'tspace_1dim');
|
||||||
SELECT attach_tablespace('tablespace2', 'tspace_1dim');
|
SELECT attach_tablespace('tablespace2', 'tspace_1dim');
|
||||||
|
|
||||||
SELECT * FROM _timescaledb_catalog.tablespace;
|
SELECT * FROM _timescaledb_catalog.tablespace;
|
||||||
@ -80,9 +82,15 @@ SELECT * FROM _timescaledb_catalog.tablespace;
|
|||||||
INSERT INTO tspace_1dim VALUES ('2017-01-20T09:00:01', 24.3, 'blue');
|
INSERT INTO tspace_1dim VALUES ('2017-01-20T09:00:01', 24.3, 'blue');
|
||||||
INSERT INTO tspace_1dim VALUES ('2017-03-20T09:00:01', 24.3, 'brown');
|
INSERT INTO tspace_1dim VALUES ('2017-03-20T09:00:01', 24.3, 'brown');
|
||||||
|
|
||||||
SELECT relname, spcname FROM pg_class c
|
SELECT * FROM test.show_subtablesp('tspace_%');
|
||||||
INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid)
|
--indexes should inherit the tablespace of their chunk, unless the
|
||||||
INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname);
|
--parent index has a tablespace set, in which case the chunks'
|
||||||
|
--corresponding indexes are pinned to the parent index's
|
||||||
|
--tablespace. The parent index can have a tablespace set in two cases:
|
||||||
|
--(1) if explicitly set in CREATE INDEX, or (2) if the main table was
|
||||||
|
--created with a tablespace, because then default indexes will be
|
||||||
|
--created in that tablespace too.
|
||||||
|
SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk');
|
||||||
|
|
||||||
--detach tablespace1 from all tables. Due to lack of permissions,
|
--detach tablespace1 from all tables. Due to lack of permissions,
|
||||||
--should only detach from 'tspace_1dim' (1 tablespace)
|
--should only detach from 'tspace_1dim' (1 tablespace)
|
||||||
|
@ -198,19 +198,22 @@ END
|
|||||||
$BODY$;
|
$BODY$;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION test.show_subtables(rel regclass)
|
CREATE OR REPLACE FUNCTION test.show_subtables(rel regclass)
|
||||||
RETURNS TABLE("Child" regclass) LANGUAGE SQL STABLE AS
|
RETURNS TABLE("Child" regclass,
|
||||||
|
"Tablespace" name) LANGUAGE SQL STABLE AS
|
||||||
$BODY$
|
$BODY$
|
||||||
SELECT objid::regclass
|
SELECT objid::regclass, (SELECT t.spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace)
|
||||||
FROM pg_depend d
|
FROM pg_depend d, pg_class c
|
||||||
WHERE d.refobjid = rel
|
WHERE d.refobjid = rel
|
||||||
AND d.deptype = 'n'
|
AND d.deptype = 'n'
|
||||||
AND d.classid = 'pg_class'::regclass
|
AND d.classid = 'pg_class'::regclass
|
||||||
|
AND d.objid = c.oid
|
||||||
ORDER BY d.refobjid, d.objid;
|
ORDER BY d.refobjid, d.objid;
|
||||||
$BODY$;
|
$BODY$;
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION test.show_subtablesp(pattern text)
|
CREATE OR REPLACE FUNCTION test.show_subtablesp(pattern text)
|
||||||
RETURNS TABLE("Parent" regclass,
|
RETURNS TABLE("Parent" regclass,
|
||||||
"Child" regclass) LANGUAGE PLPGSQL STABLE AS
|
"Child" regclass,
|
||||||
|
"Tablespace" name) LANGUAGE PLPGSQL STABLE AS
|
||||||
$BODY$
|
$BODY$
|
||||||
DECLARE
|
DECLARE
|
||||||
schema_name name = split_part(pattern, '.', 1);
|
schema_name name = split_part(pattern, '.', 1);
|
||||||
@ -223,7 +226,8 @@ BEGIN
|
|||||||
|
|
||||||
RETURN QUERY
|
RETURN QUERY
|
||||||
SELECT refobjid::regclass,
|
SELECT refobjid::regclass,
|
||||||
objid::regclass
|
objid::regclass,
|
||||||
|
(SELECT t.spcname FROM pg_class cc, pg_tablespace t WHERE cc.oid = d.objid AND t.oid = cc.reltablespace)
|
||||||
FROM pg_class c, pg_depend d
|
FROM pg_class c, pg_depend d
|
||||||
WHERE format('%I.%I', c.relnamespace::regnamespace::name, c.relname) LIKE format('%I.%s', schema_name, table_name)
|
WHERE format('%I.%I', c.relnamespace::regnamespace::name, c.relname) LIKE format('%I.%s', schema_name, table_name)
|
||||||
AND d.refobjid = c.oid
|
AND d.refobjid = c.oid
|
||||||
|
Loading…
x
Reference in New Issue
Block a user