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
|
* GetHighestUsedAddress returns the highest used address for the given
|
||||||
* relfilenode across all active and inactive transactions.
|
* 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
|
uint64
|
||||||
GetHighestUsedAddress(RelFileNode relfilenode)
|
GetHighestUsedAddress(RelFileNode relfilenode)
|
||||||
{
|
{
|
||||||
uint64 highestUsedAddress = 0;
|
uint64 highestUsedAddress = 0;
|
||||||
uint64 highestUsedId = 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);
|
GetHighestUsedAddressAndId(metapage->storageId, &highestUsedAddress, &highestUsedId);
|
||||||
|
|
||||||
|
|
|
@ -743,7 +743,8 @@ LogRelationStats(Relation rel, int elevel)
|
||||||
appendStringInfo(infoBuf,
|
appendStringInfo(infoBuf,
|
||||||
"total row count: %ld, stripe count: %d, "
|
"total row count: %ld, stripe count: %d, "
|
||||||
"average rows per stripe: %ld\n",
|
"average rows per stripe: %ld\n",
|
||||||
tupleCount, stripeCount, tupleCount / stripeCount);
|
tupleCount, stripeCount,
|
||||||
|
stripeCount ? tupleCount / stripeCount : 0);
|
||||||
appendStringInfo(infoBuf,
|
appendStringInfo(infoBuf,
|
||||||
"block count: %ld"
|
"block count: %ld"
|
||||||
", containing data for dropped columns: %ld",
|
", containing data for dropped columns: %ld",
|
||||||
|
@ -817,7 +818,11 @@ TruncateCStore(Relation rel, int elevel)
|
||||||
SmgrAddr highestPhysicalAddress =
|
SmgrAddr highestPhysicalAddress =
|
||||||
logical_to_smgr(GetHighestUsedAddress(rel->rd_node));
|
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)
|
if (new_rel_pages == old_rel_pages)
|
||||||
{
|
{
|
||||||
UnlockRelation(rel, AccessExclusiveLock);
|
UnlockRelation(rel, AccessExclusiveLock);
|
||||||
|
|
|
@ -8,6 +8,7 @@ test: am_query
|
||||||
test: am_analyze
|
test: am_analyze
|
||||||
test: am_data_types
|
test: am_data_types
|
||||||
test: am_drop
|
test: am_drop
|
||||||
|
test: am_empty
|
||||||
test: am_insert
|
test: am_insert
|
||||||
test: am_copyto
|
test: am_copyto
|
||||||
test: am_alter
|
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