blob: 01b00fc0b5af063137427ff2ead9c8378c4dcff5 [file] [log] [blame]
--
-- Tests the spill files disk space accounting mechanism
--
-- CBDB_PARALLEL_FIXME: it's hard to make fault_injection work with prallel processes.
set enable_parallel = false;
-- check segspace before test
reset statement_mem;
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
--- create and populate the table
DROP TABLE IF EXISTS segspace_test_hj_skew;
CREATE TABLE segspace_test_hj_skew (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 int) DISTRIBUTED BY (i1);
set gp_autostats_mode = none;
-- many values with i1 = 1
INSERT INTO segspace_test_hj_skew SELECT 1,i,i,i,i,i,i,i FROM
(select generate_series(1, nsegments * 50000) as i from
(select count(*) as nsegments from gp_segment_configuration where role='p' and content >= 0) foo) bar;
-- some nicely distributed values
INSERT INTO segspace_test_hj_skew SELECT i,i,i,i,i,i,i,i FROM
(select generate_series(1, nsegments * 100000) as i from
(select count(*) as nsegments from gp_segment_configuration where role='p' and content >= 0) foo) bar;
ANALYZE segspace_test_hj_skew;
--
-- Testing that query cancelation during spilling updates the accounting
--
------------ Interrupting SELECT query that spills -------------------
-- enable the fault injector
select gp_inject_fault('exec_hashjoin_new_batch', 'reset', 2);
select gp_inject_fault('exec_hashjoin_new_batch', 'interrupt', 2);
set statement_mem=2048;
set gp_autostats_mode = none;
begin;
SELECT t1.* FROM segspace_test_hj_skew AS t1, segspace_test_hj_skew AS t2 WHERE t1.i1=t2.i2;
rollback;
--
-- GPDB parallel once got errors like:
-- could not read from shared tuplestore temporary file: read only 0 of 8 bytes from file.
-- Enable parallel here to test it.
--
begin;
set local enable_parallel = true;
set local optimizer=off;
set local min_parallel_table_scan_size=0;
set local min_parallel_index_scan_size = 0;
set local force_parallel_mode=1;
EXPLAIN(COSTS OFF) SELECT t1.* FROM segspace_test_hj_skew AS t1, segspace_test_hj_skew AS t2 WHERE t1.i1=t2.i2;
SELECT count(t1.*) FROM segspace_test_hj_skew AS t1, segspace_test_hj_skew AS t2 WHERE t1.i1=t2.i2;
rollback;
select gp_inject_fault('exec_hashjoin_new_batch', 'status', 2);
-- check used segspace after test
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
-- Run the test without fault injection
begin;
-- Doing select count so output file doesn't have 75000 rows.
select count(*) from
(SELECT t1.* FROM segspace_test_hj_skew AS t1, segspace_test_hj_skew AS t2 WHERE t1.i1=t2.i2) temp;
rollback;
-- check used segspace after test
reset statement_mem;
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
------------ Interrupting INSERT INTO query that spills -------------------
drop table if exists segspace_t1_created;
create table segspace_t1_created (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 int) DISTRIBUTED BY (i1);
set statement_mem=2048;
set gp_autostats_mode = none;
-- enable the fault injector
select gp_inject_fault('exec_hashjoin_new_batch', 'reset', 2);
select gp_inject_fault('exec_hashjoin_new_batch', 'interrupt', 2);
begin;
insert into segspace_t1_created
SELECT t1.* FROM segspace_test_hj_skew AS t1, segspace_test_hj_skew AS t2 WHERE t1.i1=t2.i2;
rollback;
select gp_inject_fault('exec_hashjoin_new_batch', 'status', 2);
-- check used segspace after test
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
-- Run the test without fault injection
begin;
insert into segspace_t1_created
SELECT t1.* FROM segspace_test_hj_skew AS t1, segspace_test_hj_skew AS t2 WHERE t1.i1=t2.i2;
rollback;
-- check used segspace after test
reset statement_mem;
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
--start_ignore
drop table if exists segspace_t1_created;
--end_ignore
------------ Interrupting CREATE TABLE AS query that spills -------------------
drop table if exists segspace_t1_created;
set statement_mem=2048;
set gp_autostats_mode = none;
-- enable the fault injector
select gp_inject_fault('exec_hashjoin_new_batch', 'reset', 2);
select gp_inject_fault('exec_hashjoin_new_batch', 'interrupt', 2);
begin;
create table segspace_t1_created AS
SELECT t1.* FROM segspace_test_hj_skew AS t1, segspace_test_hj_skew AS t2 WHERE t1.i1=t2.i2;
rollback;
select gp_inject_fault('exec_hashjoin_new_batch', 'status', 2);
-- check used segspace after test
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
-- Run the test without fault injection
begin;
create table segspace_t1_created AS
SELECT t1.* FROM segspace_test_hj_skew AS t1, segspace_test_hj_skew AS t2 WHERE t1.i1=t2.i2;
rollback;
-- check used segspace after test
reset statement_mem;
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
------------ workfile_limit_per_segment leak check during ERROR on UPDATE with CTE and MK_SORT -------------------
drop table if exists testsisc;
drop table if exists foo;
create table testsisc (i1 int, i2 int, i3 int, i4 int);
insert into testsisc select i, i % 1000, i % 100000, i % 75 from
(select generate_series(1, nsegments * 100000) as i from
(select count(*) as nsegments from gp_segment_configuration where role='p' and content >= 0) foo) bar;
create table foo (i int, j int);
set statement_mem=1024; -- 1mb for 3 segment to get leak.
set gp_resqueue_print_operator_memory_limits=on;
set gp_cte_sharing=on;
-- enable the fault injector
select gp_inject_fault('workfile_write_failure', 'reset', 2);
select gp_inject_fault('workfile_write_failure', 'error', 2);
-- LEAK in UPDATE: update with sisc xslice sort
update foo set j=m.cc1 from (
with ctesisc as
(select * from testsisc order by i2)
select t1.i1 as cc1, t1.i2 as cc2
from ctesisc as t1, ctesisc as t2
where t1.i1 = t2.i2 ) as m;
select gp_inject_fault('exec_hashjoin_new_batch', 'status', 2);
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
-- Run the test without fault injection
-- LEAK in UPDATE: update with sisc xslice sort
update foo set j=m.cc1 from (
with ctesisc as
(select * from testsisc order by i2)
select t1.i1 as cc1, t1.i2 as cc2
from ctesisc as t1, ctesisc as t2
where t1.i1 = t2.i2 ) as m;
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
reset statement_mem;
reset gp_resqueue_print_operator_memory_limits;
reset gp_cte_sharing;
------------ workfile_limit_per_segment leak check during ERROR on DELETE with APPEND-ONLY table -------------------
drop table if exists testsisc;
drop table if exists foo;
create table testsisc (i1 int, i2 int, i3 int, i4 int) WITH (appendonly=true, compresstype=zlib) ;
insert into testsisc select i, i % 1000, i % 100000, i % 75 from
(select generate_series(1, nsegments * 100000) as i from
(select count(*) as nsegments from gp_segment_configuration where role='p' and content >= 0) foo) bar;
create table foo (i int, j int) WITH (appendonly=true, compresstype=zlib);
insert into foo select i, i % 1000 from
(select generate_series(1, nsegments * 100000) as i from
(select count(*) as nsegments from gp_segment_configuration where role='p' and content >= 0) foo) bar;
set statement_mem=1024; -- 1mb for 3 segment to get leak.
-- enable the fault injector
select gp_inject_fault('workfile_write_failure', 'reset', 2);
select gp_inject_fault('workfile_write_failure', 'error', 2);
-- LEAK in DELETE with APPEND ONLY tables
delete from testsisc using (
select *
from foo
) src where testsisc.i1 = src.i;
select gp_inject_fault('exec_hashjoin_new_batch', 'status', 2);
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
-- Run the test without fault injection
-- LEAK in DELETE with APPEND ONLY tables
delete from testsisc using (
select *
from foo
) src where testsisc.i1 = src.i;
reset statement_mem;
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
------------ workfile_limit_per_segment leak check during UPDATE of SORT -------------------
drop table if exists testsort;
create table testsort (i1 int, i2 int, i3 int, i4 int);
insert into testsort select i, i % 1000, i % 100000, i % 75 from generate_series(0,1000000) i;
analyze testsort;
set statement_mem="1MB";
drop table if exists foo;
create table foo (c int, d int);
insert into foo values (1, 1);
-- enable the fault injector
select gp_inject_fault('workfile_write_failure', 'reset', 2);
select gp_inject_fault('workfile_write_failure', 'error', 2);
-- expect to see leak if we hit error
update foo set d = i1 from (select i1,i2 from testsort order by i2) x;
-- check counter leak
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
select gp_inject_fault('exec_hashjoin_new_batch', 'status', 2);
-- Run the test without fault injection
-- expect to see leak if we hit error
-- start_ignore
update foo set d = i1 from (select i1,i2 from testsort order by i2) x;
-- end_ignore
-- check counter leak
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
drop table testsort;
------------ workfile_limit_per_segment leak check during UPDATE of SHARE_SORT_XSLICE -------------------
drop table if exists testsisc;
create table testsisc (i1 int, i2 int, i3 int, i4 int);
insert into testsisc select i, i % 1000, i % 100000, i % 75 from generate_series(0,1000000) i;
set statement_mem="2MB";
set gp_cte_sharing=on;
drop table if exists foo;
create table foo (c int, d int);
-- expect to see leak if we hit error
-- enable the fault injector
select gp_inject_fault('workfile_write_failure', 'reset', 2);
select gp_inject_fault('workfile_write_failure', 'error', 2);
update foo set d = i1 from (with ctesisc as (select * from testsisc order by i2)
select * from
(select count(*) from ctesisc) x(a), ctesisc
where x.a = ctesisc.i1) y;
select gp_inject_fault('exec_hashjoin_new_batch', 'status', 2);
-- check counter leak
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
-- Run the test without fault injection
update foo set d = i1 from (with ctesisc as (select * from testsisc order by i2)
select * from
(select count(*) from ctesisc) x(a), ctesisc
where x.a = ctesisc.i1) y;
-- check counter leak
select max(bytes) as max, min(bytes) as min from gp_toolkit.gp_workfile_mgr_used_diskspace;
-- Check if we delete workfile_set at each subtransaction.
-- This test doesn't depend on the guc `gp_workfile_limit_per_segment` like rest
-- start_ignore
drop external table if exists exttest;
create external web table exttest (x int)
execute E'echo 1; echo 2; echo 3; echo bogus; echo 5'
on master
format 'text';
-- end_ignore
create or replace function workset_cleanup_test()
returns boolean as
$func$
declare
sub_work_set_cnt integer;
top_work_set_cnt integer;
begin
select count(*) into top_work_set_cnt from gp_toolkit.gp_workfile_entries;
for i in 1..2 loop
begin
select * from exttest a, exttest b;
exception when others then
raise notice 'caught exception: %', sqlerrm;
end;
select count(*) into sub_work_set_cnt from gp_toolkit.gp_workfile_entries;
end loop;
return top_work_set_cnt = sub_work_set_cnt;
end;
$func$ language plpgsql;
select workset_cleanup_test();
drop table segspace_test_hj_skew;
reset enable_parallel;
-- don't disturb other processes.
select cleanupAllGangs();