mirror of https://github.com/citusdata/citus.git
Columnar: Fix VACUUM for empty tables
parent
c4f36c195f
commit
24bfd368a9
|
@ -607,13 +607,23 @@ StripesForRelfilenode(RelFileNode relfilenode)
|
|||
/*
|
||||
* GetHighestUsedAddress returns the highest used address for the given
|
||||
* relfilenode across all active and inactive transactions.
|
||||
*
|
||||
* This is used by truncate stage of VACUUM, and VACUUM can be called
|
||||
* for empty tables. So this doesn't throw errors for empty tables and
|
||||
* returns 0.
|
||||
*/
|
||||
uint64
|
||||
GetHighestUsedAddress(RelFileNode relfilenode)
|
||||
{
|
||||
uint64 highestUsedAddress = 0;
|
||||
uint64 highestUsedId = 0;
|
||||
ColumnarMetapage *metapage = ReadMetapage(relfilenode, false);
|
||||
ColumnarMetapage *metapage = ReadMetapage(relfilenode, true);
|
||||
|
||||
/* empty data file? */
|
||||
if (metapage == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GetHighestUsedAddressAndId(metapage->storageId, &highestUsedAddress, &highestUsedId);
|
||||
|
||||
|
|
|
@ -743,7 +743,8 @@ LogRelationStats(Relation rel, int elevel)
|
|||
appendStringInfo(infoBuf,
|
||||
"total row count: %ld, stripe count: %d, "
|
||||
"average rows per stripe: %ld\n",
|
||||
tupleCount, stripeCount, tupleCount / stripeCount);
|
||||
tupleCount, stripeCount,
|
||||
stripeCount ? tupleCount / stripeCount : 0);
|
||||
appendStringInfo(infoBuf,
|
||||
"block count: %ld"
|
||||
", containing data for dropped columns: %ld",
|
||||
|
@ -817,7 +818,11 @@ TruncateCStore(Relation rel, int elevel)
|
|||
SmgrAddr highestPhysicalAddress =
|
||||
logical_to_smgr(GetHighestUsedAddress(rel->rd_node));
|
||||
|
||||
BlockNumber new_rel_pages = highestPhysicalAddress.blockno + 1;
|
||||
/*
|
||||
* Unlock and return if truncation won't reduce data file's size.
|
||||
*/
|
||||
BlockNumber new_rel_pages = Min(old_rel_pages,
|
||||
highestPhysicalAddress.blockno + 1);
|
||||
if (new_rel_pages == old_rel_pages)
|
||||
{
|
||||
UnlockRelation(rel, AccessExclusiveLock);
|
||||
|
|
|
@ -8,6 +8,7 @@ test: am_query
|
|||
test: am_analyze
|
||||
test: am_data_types
|
||||
test: am_drop
|
||||
test: am_empty
|
||||
test: am_insert
|
||||
test: am_copyto
|
||||
test: am_alter
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
--
|
||||
-- Test different operations on empty columnar tables.
|
||||
--
|
||||
SET citus.compression to 'none';
|
||||
create table t_uncompressed(a int) using columnar;
|
||||
create table t_compressed(a int) using columnar;
|
||||
-- set options
|
||||
SELECT alter_columnar_table_set('t_compressed', compression => 'pglz');
|
||||
alter_columnar_table_set
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT alter_columnar_table_set('t_compressed', stripe_row_count => 100);
|
||||
alter_columnar_table_set
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT alter_columnar_table_set('t_compressed', block_row_count => 100);
|
||||
alter_columnar_table_set
|
||||
---------------------------------------------------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM cstore.options WHERE regclass = 't_compressed'::regclass;
|
||||
regclass | block_row_count | stripe_row_count | compression
|
||||
---------------------------------------------------------------------
|
||||
t_compressed | 100 | 100 | pglz
|
||||
(1 row)
|
||||
|
||||
-- select
|
||||
select * from t_uncompressed;
|
||||
a
|
||||
---------------------------------------------------------------------
|
||||
(0 rows)
|
||||
|
||||
select count(*) from t_uncompressed;
|
||||
count
|
||||
---------------------------------------------------------------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
select * from t_compressed;
|
||||
a
|
||||
---------------------------------------------------------------------
|
||||
(0 rows)
|
||||
|
||||
select count(*) from t_compressed;
|
||||
count
|
||||
---------------------------------------------------------------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
-- explain
|
||||
explain (costs off, summary off, timing off) select * from t_uncompressed;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (CStoreScan) on t_uncompressed
|
||||
(1 row)
|
||||
|
||||
explain (costs off, summary off, timing off) select * from t_compressed;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (CStoreScan) on t_compressed
|
||||
(1 row)
|
||||
|
||||
-- vacuum
|
||||
vacuum verbose t_compressed;
|
||||
INFO: statistics for "t_compressed":
|
||||
storage id: -1
|
||||
total file size: 0, total data size: 0
|
||||
total row count: 0, stripe count: 0, average rows per stripe: 0
|
||||
block count: 0, containing data for dropped columns: 0, none compressed: 0, pglz compressed: 0
|
||||
|
||||
vacuum verbose t_uncompressed;
|
||||
INFO: statistics for "t_uncompressed":
|
||||
storage id: -1
|
||||
total file size: 0, total data size: 0
|
||||
total row count: 0, stripe count: 0, average rows per stripe: 0
|
||||
block count: 0, containing data for dropped columns: 0, none compressed: 0, pglz compressed: 0
|
||||
|
||||
-- vacuum full
|
||||
vacuum full t_compressed;
|
||||
vacuum full t_uncompressed;
|
||||
-- analyze
|
||||
analyze t_uncompressed;
|
||||
analyze t_compressed;
|
||||
-- truncate
|
||||
truncate t_uncompressed;
|
||||
truncate t_compressed;
|
||||
-- alter type
|
||||
alter table t_uncompressed alter column a type text;
|
||||
alter table t_compressed alter column a type text;
|
||||
-- drop
|
||||
drop table t_compressed;
|
||||
drop table t_uncompressed;
|
|
@ -0,0 +1,48 @@
|
|||
--
|
||||
-- Test different operations on empty columnar tables.
|
||||
--
|
||||
|
||||
SET citus.compression to 'none';
|
||||
create table t_uncompressed(a int) using columnar;
|
||||
create table t_compressed(a int) using columnar;
|
||||
|
||||
-- set options
|
||||
SELECT alter_columnar_table_set('t_compressed', compression => 'pglz');
|
||||
SELECT alter_columnar_table_set('t_compressed', stripe_row_count => 100);
|
||||
SELECT alter_columnar_table_set('t_compressed', block_row_count => 100);
|
||||
|
||||
SELECT * FROM cstore.options WHERE regclass = 't_compressed'::regclass;
|
||||
|
||||
-- select
|
||||
select * from t_uncompressed;
|
||||
select count(*) from t_uncompressed;
|
||||
select * from t_compressed;
|
||||
select count(*) from t_compressed;
|
||||
|
||||
-- explain
|
||||
explain (costs off, summary off, timing off) select * from t_uncompressed;
|
||||
explain (costs off, summary off, timing off) select * from t_compressed;
|
||||
|
||||
-- vacuum
|
||||
vacuum verbose t_compressed;
|
||||
vacuum verbose t_uncompressed;
|
||||
|
||||
-- vacuum full
|
||||
vacuum full t_compressed;
|
||||
vacuum full t_uncompressed;
|
||||
|
||||
-- analyze
|
||||
analyze t_uncompressed;
|
||||
analyze t_compressed;
|
||||
|
||||
-- truncate
|
||||
truncate t_uncompressed;
|
||||
truncate t_compressed;
|
||||
|
||||
-- alter type
|
||||
alter table t_uncompressed alter column a type text;
|
||||
alter table t_compressed alter column a type text;
|
||||
|
||||
-- drop
|
||||
drop table t_compressed;
|
||||
drop table t_uncompressed;
|
Loading…
Reference in New Issue