| -- start_matchsubs |
| -- m/^LOG.*PartitionSelector/ |
| -- s/^LOG.*PartitionSelector/PartitionSelector/ |
| -- m/^LOG.*Feature not supported/ |
| -- s/^LOG.*Feature not supported/Feature not supported/ |
| -- end_matchsubs |
| -- start_matchignore |
| -- m/^LOG: Missing statistics for column: .*/ |
| -- end_matchignore |
| -- start_ignore |
| DROP DATABASE IF EXISTS incrementalanalyze; |
| CREATE DATABASE incrementalanalyze; |
| ALTER DATABASE incrementalanalyze SET lc_monetary TO 'C'; |
| \c incrementalanalyze |
| DROP SCHEMA IF EXISTS incremental_analyze; |
| CREATE SCHEMA incremental_analyze; |
| -- end_ignore |
| -- Test ANALYZE for different data types |
| -- Case 1: Partitions have MCVs but after merge, none of the partition MCVs |
| -- qualify as a global MCV for the root and they are used to create the |
| -- root histogram |
| DROP TABLE IF EXISTS foo; |
| SET default_statistics_target = 4; |
| CREATE TYPE inc_analyze_composite AS |
| ( |
| a numeric, |
| b numeric |
| ); |
| CREATE TABLE foo ( |
| a int, |
| b int, |
| c03_bigint bigint, |
| c04_bigserial bigserial, |
| c05_bit bit, |
| c06_bit_varying_10 bit varying(10), |
| c07_bool bool, |
| c08_char char, |
| c09_varchar_10 varchar(10), |
| c10_cidr cidr, |
| c11_date date, |
| c12_numeric_8_2 numeric(8,2), |
| c13_float8 float8, |
| c14_inet inet, |
| c15_int4 int4, |
| c16_interval interval, |
| c17_macaddr macaddr, |
| c18_money money, |
| c19_float4 float4, |
| c20_serial4 serial4, |
| c21_smallint smallint, |
| c22_text text, |
| c23_time time, |
| c24_timetz timetz, |
| c25_timestamp timestamp, |
| c26_timestamptz timestamptz, |
| c27_uuid uuid, |
| c28_tsquery tsquery, |
| c29_varchararray character varying(2)[], |
| c30_intarray int[], |
| c31_bigintarray bigint[], |
| c33_bitarray bit(1)[], |
| c34_bitvaryingarray bit varying(10)[], |
| c35_boolarray boolean[], |
| c36_chararray character(1)[], |
| c37_cidrarray cidr[], |
| c38_datearray date[], |
| c39_numericarray numeric[], |
| c40_float8array double precision[], |
| c41_inetarray inet[], |
| c42_int4array integer[], |
| c43_intervalarray interval[], |
| c44_macaddrarray macaddr[], |
| c45_moneyarray money[], |
| c46_float4array real[], |
| c47_smallintarrayn smallint[], |
| c48_textarray text[], |
| c49_timearray time without time zone[], |
| c50_timetzarray time with time zone[], |
| c51_timestamparray timestamp without time zone[], |
| c52_timestamptzarray timestamp with time zone[], |
| c53_uuidzarray uuid[], |
| c54_tsqueryarray tsquery[], |
| c55_jsonarray json[], |
| c57_pointarray point[], |
| c58_linesegarray lseg[], |
| c59_patharray path[], |
| c60_boxarray box[], |
| c61_polygonarray polygon[], |
| c62_circlearray circle[], |
| c63_inc_analyze_composite_array inc_analyze_composite[] |
| ) PARTITION BY RANGE (b) (START (0) END(6) EVERY(3)); |
| CREATE TYPE input_fields AS |
| ( |
| varchararray character varying(2)[], |
| intarray int[], |
| _bigintarray bigint[], |
| bitarray bit(1)[], |
| bitvaryingarray bit varying(10)[], |
| boolarray boolean[], |
| chararray character(1)[], |
| cidrarray cidr[], |
| datearray date[], |
| numericarray numeric[], |
| float8array double precision[], |
| inetarray inet[], |
| int4array integer[], |
| intervalarray interval[], |
| macaddrarray macaddr[], |
| moneyarray money[], |
| float4array real[], |
| smallintarrayn smallint[], |
| textarray text[], |
| timearray time without time zone[], |
| timetzarray time with time zone[], |
| timestamparray timestamp without time zone[], |
| timestamptzarray timestamp with time zone[], |
| uuidzarray uuid[], |
| tsqueryarray tsquery[], |
| jsonarray json[], |
| pointarray point[], |
| linesegarray lseg[], |
| patharray path[], |
| boxarray box[], |
| polygonarray polygon[], |
| circlearray circle[], |
| inc_analyze_composite_array inc_analyze_composite[] |
| ); |
| |
| CREATE OR REPLACE FUNCTION get_input_fields(i INT) RETURNS input_fields AS $$ |
| DECLARE |
| fields input_fields; |
| BEGIN |
| SELECT |
| ARRAY['a' || (i % 6), 'b' || (i % 6)]::character varying(2)[], |
| ARRAY[i, i % 6]::int[], |
| ARRAY[(i % 6), ((i + 1) % 6)]::bigint[], |
| ARRAY[i, (i + 1)]::bit[], |
| ARRAY[(i % 6)::bit(10), ((i + 1) % 6)::bit(10)]::bit varying(10)[], |
| ARRAY[(i % 2), ((i + 1) % 2)]::bool[], |
| ARRAY['a' || i, 'b' || i]::char[], |
| ARRAY['192.168.100.' || (i % 6), '192.168.101.' || (i % 6)]::cidr[], |
| ARRAY['2018-01-' || ((i % 6) + 1), '2018-01-' || ((i % 6) + 1)]::date[], |
| ARRAY[(i % 6), ((i + 1) % 6)]::numeric[], |
| ARRAY[(i % 6), ((i + 1) % 6)]::float8[], |
| ARRAY['192.168.100.' || (i % 6), '192.168.100.' || ((i + 1) % 6)]::inet[], |
| ARRAY[(i % 6), ((i + 1) % 6)]::int4[], |
| '{"1 hour", "1 hour"}'::interval[], |
| ARRAY['08:00:2b:01:02:' || (i % 6), '08:00:2b:01:02:' || (i % 6)]::macaddr[], |
| ARRAY['123.4', '234.5']::money[], |
| ARRAY[(i % 6), ((i + 1) % 6)]::float4[], |
| ARRAY[(i % 6), ((i + 1) % 6)]::smallint[], |
| ARRAY['abcd' || (i % 6), 'def' || ((i + 1) % 6)]::text[], |
| ARRAY[(i % 6) || ':00:00', ((i + 1) % 6) || ':00:00']::time[], |
| ARRAY[(i % 6) || ':00:59 PST', ((i + 1) % 6) || ':00:59 EST']::timetz[], |
| ARRAY['2018-01-01 ' || (i % 6) || ':59:00', '2018-01-01 ' || ((i + 1) % 6) || ':59:00']::timestamp[], |
| ARRAY['2018-01-01 ' || (i % 6) || ':59:00 PST', '2018-01-01 ' || ((i + 1) % 6) || ':59:00 EST']::timestamptz[], |
| ARRAY['11111111-1111-1111-1111-1111111111' || (i % 6) || (i % 6), '11111111-1111-1111-1111-1111111111' || ((i + 1) % 6) || ((i + 1) % 6)]::uuid[], |
| ARRAY['foo' || (i % 6) || ' & rat', 'rat' || (i % 6) || ' & foo']::tsquery[], |
| ARRAY['{"a": "b"}', '{"c": "d"}']::json[], |
| ARRAY[point(i, i + 1), point(i + 2, i + 3)], |
| ARRAY[lseg(point(i, i + 1), point(i + 2, i + 3)), lseg(point(i + 4, i + 5), point(i + 6, i + 7))], |
| ARRAY[path(polygon(box(point(i + 1, i + 2), point(i + 3, i + 4)))), path(polygon(box(point(i + 1, i + 2), point(i + 3, i + 4))))], |
| ARRAY[box(point(i + 1, i + 2), point(i + 3, i + 4)), box(point(i + 1, i + 2), point(i + 3, i + 4))], |
| ARRAY[polygon(box(point(i + 1, i + 2), point(i + 3, i + 4))), polygon(box(point(i + 1, i + 2), point(i + 3, i + 4)))], |
| ARRAY[circle(point(i + 1, i + 2), i + 3), circle(point(i + 4, i + 5), i + 6)], |
| ARRAY[ROW(i % 6, (i + 1) % 6), ROW(i % 6, (i + 1) % 6)]::inc_analyze_composite[] |
| INTO fields; |
| |
| RETURN fields; |
| END; |
| $$ LANGUAGE PLPGSQL; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%6, |
| i%6::bigint, |
| i%6, |
| i::bit, |
| (i%6)::bit(10)::bit varying(10), |
| (i%2)::bool, |
| (i%6)::char, |
| ('a'||(i%6))::varchar(10), |
| ('192.168.100.'||(i%6))::cidr, |
| ('2018-4-'||(i%6)+1)::date, |
| (i%6)::numeric(8,2), |
| (i%6)::float8, |
| inet ('192.168.100.'||(i%6)), |
| i%6::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%6)::text)::text::macaddr, |
| (i%6)::text::money, |
| (i%6)::float4, |
| i%6, |
| i%6, |
| 'aa'||(i%6)::text, |
| ((i%6)::text||':59:59')::time, |
| ((i%6)::text||':59:00 EST')::timetz, |
| ('2018-01-01 '||(i%6)::text||':59:00')::timestamp, |
| ('2018-01-01 '||(i%6)::text||':59:00 EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%6)::text||(i%6)::text)::uuid, |
| ('foo'||(i%6)::text||' & rat'||(i%6)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,100) i; |
| ANALYZE foo; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' and attname != 'a' ORDER BY attname,tablename; |
| -- Case 2: Partitions have no MCVs, only histograms, after merge root has to |
| -- have approximately merged histograms. |
| TRUNCATE foo; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3, |
| i::bigint, |
| i, |
| i::bit, |
| (i)::bit(10)::bit varying(10), |
| (i)::bool, |
| (i)::char, |
| ('a'||(i))::varchar(10), |
| ('192.168.100.'||(i%128))::cidr, |
| ('2018-4-'||(i%15)+1)::date, |
| (i)::numeric(8,2), |
| (i)::float8, |
| inet ('192.168.100.'||(i%128)), |
| i::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%50)::text)::text::macaddr, |
| (i)::text::money, |
| (i)::float4, |
| i, |
| i, |
| 'aa'||(i)::text, |
| ((i%12)::text||':59:59')::time, |
| ((i%12)::text||':59:00 EST')::timetz, |
| ('2018-01-01 '||(i%12)::text||':59:00')::timestamp, |
| ('2018-01-01 '||(i%12)::text||':59:00 EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%5)::text||(i%5)::text)::uuid, |
| ('foo'||(i)::text||' & rat'||(i)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,100) i; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3, |
| i+200::bigint, |
| i+200, |
| i::bit, |
| (i+200)::bit(10)::bit varying(10), |
| (i+200)::bool, |
| (i+200)::char, |
| ('a'||(i+200))::varchar(10), |
| ('192.168.100.'||(i%128+128))::cidr, |
| ('2018-4-'||(i%15+16))::date, |
| (i)::numeric(8,2), |
| (i)::float8, |
| inet ('192.168.100.'||(i%128+128)), |
| i::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%50+50)::text)::text::macaddr, |
| (i)::text::money, |
| (i)::float4, |
| i, |
| i, |
| 'aa'||(i)::text, |
| ((i%12+12)::text||':59:59')::time, |
| ((i%12+12)::text||':59:00 EST')::timetz, |
| ('2018-01-01 '||(i%12+12)::text||':59:00')::timestamp, |
| ('2018-01-01 '||(i%12+12)::text||':59:00 EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%5+5)::text||(i%5+5)::text)::uuid, |
| ('foo'||(i+200)::text||' & rat'||(i+200)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,100) i; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3+3, |
| i::bigint, |
| i, |
| i::bit, |
| (i)::bit(10)::bit varying(10), |
| (i)::bool, |
| (i)::char, |
| ('a'||(i))::varchar(10), |
| ('192.168.100.'||(i%128))::cidr, |
| ('2018-4-'||(i%15)+1)::date, |
| (i)::numeric(8,2), |
| (i)::float8, |
| inet ('192.168.100.'||(i%128)), |
| i::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%50)::text)::text::macaddr, |
| (i)::text::money, |
| (i)::float4, |
| i, |
| i, |
| 'aa'||(i)::text, |
| ((i%12)::text||':59:59')::time, |
| ((i%12)::text||':59:00 EST')::timetz, |
| ('2018-01-01 '||(i%12)::text||':59:00')::timestamp, |
| ('2018-01-01 '||(i%12)::text||':59:00 EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%5)::text||(i%5)::text)::uuid, |
| ('foo'||(i)::text||' & rat'||(i)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,200) i; |
| ANALYZE foo; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| -- Case 3: Partitions have MCVs but after merge, MCVs that do not qualify as |
| -- global MCV for the root will be used to create root histograms |
| TRUNCATE foo; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3, |
| i%4::bigint, |
| i%4, |
| i::bit, |
| (i%4)::bit(10)::bit varying(10), |
| (i)::bool, |
| (i%4)::char, |
| ('a'||(i%4))::varchar(10), |
| ('192.168.100.'||(i%4))::cidr, |
| ('2018-4-'||(i%4)+1)::date, |
| (i%4)::numeric(8,2), |
| (i%4)::float8, |
| inet ('192.168.100.'||(i%4)), |
| i%4::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%4)::text)::text::macaddr, |
| (i%4)::text::money, |
| (i%4)::float4, |
| i%4, |
| i%4, |
| 'aa'||(i%4)::text, |
| ('12:'||(i%4)::text||':00')::time, |
| ('12:'||(i%4)::text||':00 EST')::timetz, |
| ('2018-01-01 '||'12:'||(i%4)::text||':00')::timestamp, |
| ('2018-01-01 '||'12:'||(i%4)::text||':00 EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%4)::text||(i%4)::text)::uuid, |
| ('foo'||(i%4)::text||' & rat'||(i%4)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,100) i; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3+3, |
| i::bigint, |
| i, |
| i::bit, |
| (i)::bit(10)::bit varying(10), |
| (i)::bool, |
| (i)::char, |
| ('a'||(i))::varchar(10), |
| ('192.168.100.'||(i))::cidr, |
| ('2018-4-'||(i%26+1))::date, |
| (i)::numeric(8,2), |
| (i)::float8, |
| inet ('192.168.100.'||(i)), |
| i::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i)::text)::text::macaddr, |
| (i)::text::money, |
| (i)::float4, |
| i, |
| i, |
| 'aa'||(i)::text, |
| ('12:'||(i%60)::text||':00')::time, |
| ('12:'||(i%60)::text||':00 EST')::timetz, |
| ('2018-01-01 '||'12:'||(i%60)::text||':00')::timestamp, |
| ('2018-01-01 '||'12:'||(i%60)::text||':00 EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%6)::text||(i%6)::text)::uuid, |
| ('foo'||(i)::text||' & rat'||(i)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,60) i; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3+3, |
| i%4+61::bigint, |
| i%4+61, |
| (i%4+61)::bit, |
| (i%4+61)::bit(10)::bit varying(10), |
| (i%4+61)::bool, |
| (i%4+61)::char, |
| ('a'||(i%4+61))::varchar(10), |
| ('192.168.100.'||(i%4+61))::cidr, |
| ('2018-4-'||(i%4)+27)::date, |
| (i%4+61)::numeric(8,2), |
| (i%4+61)::float8, |
| inet ('192.168.100.'||(i%4+61)), |
| i%4+61::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%4+61)::text)::text::macaddr, |
| (i%4+61)::text::money, |
| (i%4+61)::float4, |
| i%4+61, |
| i%4+61, |
| 'aa'||(i%4+61)::text, |
| ('12:59:'||(i%4+10)::text)::time, |
| ('12:59:'||(i%4+10)::text||' EST')::timetz, |
| ('2018-01-01 '||'12:59:'||(i%4+10)::text)::timestamp, |
| ('2018-01-01 '||'12:59:'||(i%4+10)::text||' EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%4+6)::text||(i%4+6)::text)::uuid, |
| ('foo'||(i%4)::text||' & rat'||(i%4)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,40) i; |
| ANALYZE foo; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| -- Case 4: A partition has MCVs but after merge, those MCVs do not qualify as |
| -- global MCV for the root will be used to create root histograms |
| TRUNCATE foo; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3, |
| i::bigint, |
| i, |
| i::bit, |
| (i)::bit(10)::bit varying(10), |
| (i)::bool, |
| (i)::char, |
| ('a'||(i))::varchar(10), |
| ('192.168.100.'||(i%128))::cidr, |
| ('2018-4-'||(i%15)+1)::date, |
| (i)::numeric(8,2), |
| (i)::float8, |
| inet ('192.168.100.'||(i%128)), |
| i::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%50)::text)::text::macaddr, |
| (i)::text::money, |
| (i)::float4, |
| i, |
| i, |
| 'aa'||(i)::text, |
| ((i%12)::text||':59:59')::time, |
| ((i%12)::text||':59:00 EST')::timetz, |
| ('2018-01-01 '||(i%12)::text||':59:00')::timestamp, |
| ('2018-01-01 '||(i%12)::text||':59:00 EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%5)::text||(i%5)::text)::uuid, |
| ('foo'||(i)::text||' & rat'||(i)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,100) i; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3+3, |
| i%4+61::bigint, |
| i%4+61, |
| (i%4+61)::bit, |
| (i%4+61)::bit(10)::bit varying(10), |
| (i%4+61)::bool, |
| (i%4+61)::char, |
| ('a'||(i%4+61))::varchar(10), |
| ('192.168.100.'||(i%4+61))::cidr, |
| ('2018-4-'||(i%4+26))::date, |
| (i%4+61)::numeric(8,2), |
| (i%4+61)::float8, |
| inet ('192.168.100.'||(i%4+61)), |
| i%4+61::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%4+61)::text)::text::macaddr, |
| (i%4+61)::text::money, |
| (i%4+61)::float4, |
| i%4+61, |
| i%4+61, |
| 'aa'||(i%4+61)::text, |
| ('12:'||(i%4+56)::text||':00')::time, |
| ('12:'||(i%4+56)::text||':00 EST')::timetz, |
| ('2018-01-01 '||'12:'||(i%4+56)::text||':00')::timestamp, |
| ('2018-01-01 '||'12:'||(i%4+56)::text||':00 EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%4+6)::text||(i%4+6)::text)::uuid, |
| ('foo'||(i%4+61)::text||' & rat'||(i%4+61)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,8) i; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3+3, |
| i::bigint, |
| i, |
| i::bit, |
| (i)::bit(10)::bit varying(10), |
| (i)::bool, |
| (i)::char, |
| ('a'||(i))::varchar(10), |
| ('192.168.100.'||(i))::cidr, |
| ('2018-4-'||(i%25+1))::date, |
| (i)::numeric(8,2), |
| (i)::float8, |
| inet ('192.168.100.'||(i)), |
| i::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i)::text)::text::macaddr, |
| (i)::text::money, |
| (i)::float4, |
| i, |
| i, |
| 'aa'||(i)::text, |
| ('12:00:'||(i%60)::text)::time, |
| ('12:00:'||(i%60)::text||' EST')::timetz, |
| ('2018-01-01 '||'12:00'||(i%60)::text)::timestamp, |
| ('2018-01-01 '||'12:00'||(i%60)::text||' EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%10)::text||(i%10)::text)::uuid, |
| ('foo'||(i)::text||' & rat'||(i)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,60) i; |
| ANALYZE foo; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' and attname != 'a' ORDER BY attname,tablename; |
| -- Case 5: A partition has MCVs but after merge, those MCVs qualify as global |
| -- MCVs for the root |
| TRUNCATE foo; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3, |
| i::bigint, |
| i, |
| i::bit, |
| (i)::bit(10)::bit varying(10), |
| (i)::bool, |
| (i)::char, |
| ('a'||(i))::varchar(10), |
| ('192.168.100.'||(i%128))::cidr, |
| ('2018-'||(i%12)+1||'-'||(i%15)+1)::date, |
| (i)::numeric(8,2), |
| (i)::float8, |
| inet ('192.168.100.'||(i%128)), |
| i::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%50)::text)::text::macaddr, |
| (i)::text::money, |
| (i)::float4, |
| i, |
| i, |
| 'aa'||(i)::text, |
| ('12:'||(i%60)::text||':'||(i%30)::text)::time, |
| ('12:'||(i%60)::text||':'||(i%30)::text||' EST')::timetz, |
| ('2018-01-01 '||'12:'||(i%60)::text||':'||(i%30)::text)::timestamp, |
| ('2018-01-01 '||'12:'||(i%60)::text||':'||(i%30)::text||' EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%5)::text||(i%5)::text)::uuid, |
| ('foo'||(i)::text||' & rat'||(i)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,60) i; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3+3, |
| i%4+61::bigint, |
| i%4+61, |
| (i%4+61)::bit, |
| (i%4+61)::bit(10)::bit varying(10), |
| (i%4+61)::bool, |
| (i%4+61)::char, |
| ('a'||(i%4+61))::varchar(10), |
| ('192.168.100.'||(i%4+61))::cidr, |
| ('2018-5-'||(i%4)+16)::date, |
| (i%4+61)::numeric(8,2), |
| (i%4+61)::float8, |
| inet ('192.168.100.'||(i%4+61)), |
| i%4+61::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i%4+61)::text)::text::macaddr, |
| (i%4+61)::text::money, |
| (i%4+61)::float4, |
| i%4+61, |
| i%4+61, |
| 'aa'||(i%4+61)::text, |
| ('01:00:'||(i%4)::text)::time, |
| ('01:00:'||(i%4)::text||' EST')::timetz, |
| ('2018-01-01 '||'01:00:'||(i%4)::text)::timestamp, |
| ('2018-01-01 '||'01:00:'||(i%4)::text||' EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%4+6)::text||(i%4+6)::text)::uuid, |
| ('foo'||(i%4+61)::text||' & rat'||(i%4+61)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,8) i; |
| INSERT INTO foo |
| SELECT |
| i, |
| i%3+3, |
| i::bigint, |
| i, |
| i::bit, |
| (i)::bit(10)::bit varying(10), |
| (i)::bool, |
| (i)::char, |
| ('a'||(i))::varchar(10), |
| ('192.168.100.'||(i))::cidr, |
| ('2018-'||(i%12)+1||'-'||(i%15)+1)::date, |
| (i)::numeric(8,2), |
| (i)::float8, |
| inet ('192.168.100.'||(i)), |
| i::int4, |
| interval '24 hours', |
| macaddr ('12:34:56:78:90:'||(i)::text)::text::macaddr, |
| (i)::text::money, |
| (i)::float4, |
| i, |
| i, |
| 'aa'||(i)::text, |
| ('12:'||(i%60)::text||':'||(i%30)::text)::time, |
| ('12:'||(i%60)::text||':'||(i%30)::text||' EST')::timetz, |
| ('2018-01-01 '||'12:'||(i%60)::text||':'||(i%30)::text)::timestamp, |
| ('2018-01-01 '||'12:'||(i%60)::text||':'||(i%30)::text||' EST')::timestamptz, |
| ('11111111-1111-1111-1111-1111111111'||(i%10)::text||(i%10)::text)::uuid, |
| ('foo'||(i)::text||' & rat'||(i)::text)::tsquery, |
| (get_input_fields(i)).* |
| FROM generate_series(1,10) i; |
| ANALYZE foo; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' and attname != 'a' ORDER BY attname,tablename; |
| -- Test merging leaf stats where HLL is empty |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c text) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO foo select i, i%6, repeat('aaaa', 100000) FROM generate_series(1, 100)i; |
| ANALYZE foo; |
| -- In single node, we don't 'toolarge' bitmap created in acquire_sample_rows_dispatcher. The result is more similar to postgres. |
| SELECT * FROM pg_stats WHERE tablename like 'foo%' and attname = 'c' ORDER BY attname,tablename; |
| -- Test ANALYZE full scan HLL |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c text) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO foo SELECT i, i%3, 'text_'||i%100 FROM generate_series(1,1000)i; |
| INSERT INTO foo SELECT i, i%3+3, 'text_'||i%200 FROM generate_series(1,1000)i; |
| SET default_statistics_target to 3; |
| ANALYZE FULLSCAN foo; |
| SELECT tablename, n_distinct FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| -- Test ANALYZE auto merge behavior |
| -- Do not merge stats from only one partition while other partitions have not been analyzed yet |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c int) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO foo SELECT i, i%6, i%6 FROM generate_series(1,100)i; |
| ANALYZE foo_1_prt_1; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| |
| -- Merge stats from both partitions |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c int) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO foo SELECT i, i%6, i%6 FROM generate_series(1,100)i; |
| ANALYZE foo_1_prt_1; |
| ANALYZE foo_1_prt_2; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| |
| -- No stats after merging |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c int) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| ANALYZE foo_1_prt_1; |
| ANALYZE foo_1_prt_2; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| |
| -- Merge stats from only one partition |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c int) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO foo SELECT i, i%6, i%6 FROM generate_series(1,100)i; |
| SET allow_system_table_mods=true; |
| UPDATE pg_attribute SET attstattarget=0 WHERE attrelid = 'foo_1_prt_1'::regclass and ATTNAME in ('a','b','c'); |
| ANALYZE foo_1_prt_1; |
| ANALYZE foo_1_prt_2; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| |
| -- Merge stats from only one partition one column |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c int) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO foo SELECT i, i%6, i%6 FROM generate_series(1,100)i; |
| ANALYZE foo_1_prt_1(c); |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| |
| -- Test merging of leaf stats when one partition has |
| -- FULL SCAN HLL and the other has HLL from sample |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO FOO SELECT i,i%6 FROM generate_series(1,1000)i; |
| ANALYZE foo_1_prt_1; |
| ANALYZE FULLSCAN foo_1_prt_2; |
| -- Test merging of stats for a newly added partition |
| -- Do not collect samples while merging stats |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO FOO SELECT i,i%6 FROM generate_series(1,1000)i; |
| SET default_statistics_target = 4; |
| ANALYZE foo; |
| ALTER TABLE foo ADD partition new_part START (6) INCLUSIVE END (9) EXCLUSIVE; |
| INSERT INTO foo SELECT i, i%3+6 FROM generate_series(1,500)i; |
| ANALYZE foo_1_prt_new_part; |
| SET log_statement='none'; |
| SET client_min_messages = 'log'; |
| -- Insert a new column that is not analyzed in the leaf partitions. |
| -- Analyzing root partition will use merging statistics for the first 2 columns, |
| -- will create a sample for the root to analyze the newly added columns since |
| -- the leaf partitions does not have any stats for it, yet |
| ALTER TABLE foo ADD COLUMN c int; |
| INSERT INTO foo SELECT i, i%9, i%100 FROM generate_series(1,500)i; |
| -- start_matchsubs |
| -- m/gp_acquire_sample_rows([^,]+, [^,]+, .+)/ |
| -- s/gp_acquire_sample_rows([^,]+, [^,]+, .+)/gp_acquire_sample_rows()/ |
| -- end_matchsubs |
| ANALYZE VERBOSE rootpartition foo; |
| -- Testing auto merging root statistics for all columns |
| -- where column attnums are differents due to dropped columns |
| -- and split partitions. |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c text, d int) |
| PARTITION BY RANGE (a) |
| (START (0) END (8) EVERY (4), |
| DEFAULT PARTITION def_part); |
| INSERT INTO foo SELECT i%13, i, 'something'||i::text, i%121 FROM generate_series(1,1000)i; |
| ALTER TABLE foo DROP COLUMN b; |
| ALTER TABLE foo SPLIT DEFAULT PARTITION START (8) END (12) INTO (PARTITION new_part, default PARTITION); |
| set client_min_messages to 'log'; |
| ANALYZE foo_1_prt_2; |
| ANALYZE foo_1_prt_3; |
| ANALYZE foo_1_prt_new_part; |
| ANALYZE foo_1_prt_def_part; |
| reset client_min_messages; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| -- Testing auto merging root statistics for a column whose attnum |
| -- is aligned and the same in every partition due to dropped columns |
| -- and split partitions. |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c text, d int) |
| PARTITION BY RANGE (a) |
| (START (0) END (8) EVERY (4), |
| DEFAULT PARTITION def_part); |
| INSERT INTO foo SELECT i%13, i, 'something'||i::text, i%121 FROM generate_series(1,1000)i; |
| ALTER TABLE foo DROP COLUMN b; |
| ALTER TABLE foo SPLIT DEFAULT PARTITION START (8) END (12) INTO (PARTITION new_part, default PARTITION); |
| set client_min_messages to 'log'; |
| ANALYZE foo_1_prt_2(a); |
| ANALYZE foo_1_prt_3(a); |
| ANALYZE foo_1_prt_new_part(a); |
| ANALYZE foo_1_prt_def_part(a); |
| reset client_min_messages; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| -- Testing auto merging root statistics for a column whose attnum |
| -- is not aligned and different in partitions due to dropped columns |
| -- and split partitions. |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c text, d int) |
| PARTITION BY RANGE (a) |
| (START (0) END (8) EVERY (4), |
| DEFAULT PARTITION def_part); |
| INSERT INTO foo SELECT i%13, i, 'something'||i::text, i%121 FROM generate_series(1,1000)i; |
| ALTER TABLE foo DROP COLUMN b; |
| ALTER TABLE foo SPLIT DEFAULT PARTITION START (8) END (12) INTO (PARTITION new_part, default PARTITION); |
| set client_min_messages to 'log'; |
| ANALYZE foo_1_prt_2(d); |
| ANALYZE foo_1_prt_3(d); |
| ANALYZE foo_1_prt_new_part(d); |
| ANALYZE foo_1_prt_def_part(d); |
| reset client_min_messages; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| -- Testing ANALYZE ROOTPARTITION and when optimizer_analyze_root_partition is off |
| -- for incremental analyze. |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c text) |
| PARTITION BY RANGE (b) |
| (START (0) END (8) EVERY (4)); |
| INSERT INTO foo SELECT i%130, i%8, 'something'||i::text FROM generate_series(1,1000)i; |
| set optimizer_analyze_root_partition=off; |
| set client_min_messages to 'log'; |
| -- ANALYZE ROOTPARTITION will sample the table and compute statistics since there |
| -- is not stats to be merged in the leaf partitions |
| ANALYZE ROOTPARTITION foo; |
| reset client_min_messages; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| ANALYZE foo_1_prt_1; |
| ANALYZE foo_1_prt_2; |
| set client_min_messages to 'log'; |
| -- ANALYZE ROOT PARTITION will piggyback on the stats collected from the leaf and merge them |
| ANALYZE ROOTPARTITION foo; |
| reset client_min_messages; |
| reset optimizer_analyze_root_partition; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| -- Testing that auto merge will be disabled when optimizer_analyze_root_partition |
| -- is off for incremental analyze. |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c text) |
| PARTITION BY RANGE (b) |
| (START (0) END (8) EVERY (4)); |
| INSERT INTO foo SELECT i%130, i%8, 'something'||i::text FROM generate_series(1,1000)i; |
| set optimizer_analyze_root_partition=off; |
| ANALYZE foo_1_prt_1; |
| ANALYZE foo_1_prt_2; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| reset optimizer_analyze_root_partition; |
| -- Test incremental analyze on a partitioned table with different storage type and compression algorithm |
| DROP TABLE IF EXISTS incr_analyze_test; |
| CREATE TABLE incr_analyze_test ( |
| a integer, |
| b character varying, |
| c date |
| ) |
| WITH (appendonly=true, orientation=row) PARTITION BY RANGE(c) |
| ( |
| START ('2018-01-01'::date) END ('2018-01-02'::date) EVERY ('1 day'::interval) WITH (tablename='incr_analyze_test_1_prt_1', appendonly=true, compresslevel=3, orientation=column, compresstype=ZLIB ), |
| START ('2018-01-02'::date) END ('2018-01-03'::date) EVERY ('1 day'::interval) WITH (tablename='incr_analyze_test_1_prt_2', appendonly=true, compresslevel=1, orientation=column, compresstype=RLE_TYPE ), |
| START ('2018-01-03'::date) END ('2018-01-04'::date) EVERY ('1 day'::interval) WITH (tablename='incr_analyze_test_1_prt_3', appendonly=true, compresslevel=1, orientation=column, compresstype=ZLIB ), |
| START ('2018-01-04'::date) END ('2018-01-05'::date) EVERY ('1 day'::interval) WITH (tablename='incr_analyze_test_1_prt_4', appendonly=true, compresslevel=1, orientation=row, compresstype=ZLIB ), |
| START ('2018-01-05'::date) END ('2018-01-06'::date) EVERY ('1 day'::interval) WITH (tablename='incr_analyze_test_1_prt_5', appendonly=true, compresslevel=1, orientation=row, compresstype=ZLIB ), |
| START ('2018-01-06'::date) END ('2018-01-07'::date) EVERY ('1 day'::interval) WITH (tablename='incr_analyze_test_1_prt_6', appendonly=false) |
| ); |
| |
| INSERT INTO incr_analyze_test VALUES (1, 'a', '2018-01-01'); |
| ANALYZE incr_analyze_test; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'incr_analyze_test%' ORDER BY attname,tablename; |
| INSERT INTO incr_analyze_test SELECT s, md5(s::varchar), '2018-01-02' FROM generate_series(1, 1000) AS s; |
| ANALYZE incr_analyze_test_1_prt_2; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'incr_analyze_test%' ORDER BY attname,tablename; |
| SELECT relname, relpages, reltuples FROM pg_class WHERE relname LIKE 'incr_analyze_test%' ORDER BY relname; |
| -- Test merging of stats if an empty partition contains relpages > 0 |
| -- Do not collect samples while merging stats |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int) PARTITION BY RANGE (b) (START (0) END (6) EVERY (3)); |
| INSERT INTO foo SELECT i,i%3 FROM generate_series(1,10)i; |
| ANALYZE foo_1_prt_1; |
| ANALYZE foo_1_prt_2; |
| SET allow_system_table_mods = on; |
| UPDATE pg_class set relpages=3 WHERE relname='foo_1_prt_2'; |
| RESET allow_system_table_mods; |
| analyze verbose rootpartition foo; |
| -- ensure relpages is correctly set after analyzing |
| analyze foo_1_prt_2; |
| select reltuples, relpages from pg_class where relname ='foo_1_prt_2'; |
| -- Test application of column-wise statistics setting to the number of MCVs and histogram bounds on partitioned table |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int) PARTITION BY RANGE (a) (START (0) END (10) EVERY (5)); |
| -- fill foo with even numbers twice as large than odd ones to avoid fully even distribution of 'a' attribute and hence empty MCV/MCF |
| INSERT INTO foo SELECT i%10 FROM generate_series(0, 100) i; |
| INSERT INTO foo SELECT i%10 FROM generate_series(0, 100) i WHERE i%2 = 0; |
| -- default_statistics_target is 4 |
| ALTER TABLE foo ALTER COLUMN a SET STATISTICS 5; |
| ANALYZE foo; |
| SELECT array_length(most_common_vals, 1), array_length(most_common_freqs, 1), array_length(histogram_bounds, 1) FROM pg_stats WHERE tablename = 'foo' AND attname = 'a'; |
| |
| -- Make sure a simple heap table does not store HLL values |
| CREATE TABLE simple_table_no_hll (a int); |
| INSERT INTO simple_table_no_hll SELECT generate_series(1,10); |
| ANALYZE simple_table_no_hll; |
| SELECT staattnum, stakind1, stakind2, stakind3, stakind4, stakind5, |
| stavalues1, stavalues2, stavalues3, stavalues4, stavalues5 |
| FROM pg_statistic WHERE starelid = 'simple_table_no_hll'::regclass; |
| |
| -- Make sure analyze rootpartition option works in an option list |
| set optimizer_analyze_root_partition to off; |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo(a int) PARTITION BY RANGE(a) (start (0) INCLUSIVE END (20) EVERY (10)); |
| INSERT INTO foo values (5),(15); |
| ANALYZE (verbose, rootpartition off) foo; |
| |
| -- root should not have stats |
| SELECT count(*) from pg_statistic where starelid='foo'::regclass; |
| |
| -- root should have stats |
| ANALYZE (verbose, rootpartition on) foo; |
| SELECT count(*) from pg_statistic where starelid='foo'::regclass; |
| |
| -- Make sure analyze hll fullscan option works in an option list |
| ANALYZE (verbose, fullscan on) foo; |
| ANALYZE (verbose, fullscan off) foo; |
| reset optimizer_analyze_root_partition; |
| |
| -- Test merging of stats after the last partition is analyzed. Merging should |
| -- be done for root without taking a sample from root if one of the column |
| -- statistics collection is turned off |
| DROP TABLE IF EXISTS foo; |
| CREATE TABLE foo (a int, b int, c gp_hyperloglog_estimator) PARTITION BY RANGE (b) (START (1) END (3) EVERY (1)); |
| SET gp_autostats_mode=none; |
| ALTER TABLE foo ALTER COLUMN c SET STATISTICS 0; |
| INSERT INTO foo SELECT i,i%2+1, NULL FROM generate_series(1,100)i; |
| ANALYZE VERBOSE foo_1_prt_1; |
| ANALYZE VERBOSE foo_1_prt_2; |
| SELECT tablename, attname, null_frac, n_distinct, most_common_vals, most_common_freqs, histogram_bounds FROM pg_stats WHERE tablename like 'foo%' ORDER BY attname,tablename; |
| RESET gp_autostats_mode; |
| |
| -- analyze in transaction should merge leaves instead of resampling |
| drop table if exists foo; |
| create table foo (a int, b date) partition by range(b) (partition "20210101" start ('20210101'::date) end ('20210201'::date), partition "20210201" start ('20210201'::date) end ('20210301'::date), partition "20210301" start ('20210301'::date) end ('20210401'::date)); |
| insert into foo select a, '20210101'::date+a from (select generate_series(1,80) a) t1; |
| analyze verbose foo; |
| |
| -- we should see "analyzing "public.foo" inheritance tree" in the output below |
| begin; |
| truncate foo_1_prt_20210201; |
| insert into foo select a, '20210101'::date+a from (select generate_series(31,40) a) t1; |
| analyze verbose foo_1_prt_20210201; |
| rollback; |