mirror of https://github.com/citusdata/citus.git
296 lines
9.9 KiB
PL/PgSQL
296 lines
9.9 KiB
PL/PgSQL
--
|
|
-- stat_statements
|
|
--
|
|
-- tests citus_stat_statements functionality
|
|
|
|
SHOW server_version \gset
|
|
SELECT substring(:'server_version', '\d+')::int >= 14 AS server_version_ge_14
|
|
\gset
|
|
\if :server_version_ge_14
|
|
SET compute_query_id = 'on';
|
|
\endif
|
|
|
|
-- check if pg_stat_statements is available
|
|
SELECT name FROM pg_available_extensions WHERE name = 'pg_stat_statements';
|
|
|
|
SELECT regexp_split_to_array(setting, ',') @> ARRAY['pg_stat_statements'] AS stats_loaded
|
|
FROM pg_settings WHERE name = 'shared_preload_libraries';
|
|
|
|
DROP EXTENSION IF EXISTS pg_stat_statements;
|
|
-- verify it is not loaded yet
|
|
SELECT extname FROM pg_extension WHERE extname = 'pg_stat_statements';
|
|
|
|
-- this should error out since extension is not created yet
|
|
SELECT * FROM citus_stat_statements;
|
|
|
|
-- create extension if available
|
|
SELECT CASE WHEN COUNT(*) > 0 THEN
|
|
'CREATE EXTENSION pg_stat_statements'
|
|
ELSE 'SELECT false as pg_stat_statements_available' END
|
|
AS create_cmd FROM pg_available_extensions()
|
|
WHERE name = 'pg_stat_statements'
|
|
\gset
|
|
|
|
:create_cmd;
|
|
|
|
CREATE FUNCTION normalize_query_string(query_string text)
|
|
RETURNS TEXT
|
|
LANGUAGE plpgsql
|
|
AS $function$
|
|
BEGIN
|
|
RETURN rtrim(regexp_replace(query_string, '\$\d+', '?', 'g'), ';');
|
|
END;
|
|
$function$;
|
|
|
|
-- verify citus stat statements reset
|
|
SELECT citus_stat_statements_reset();
|
|
|
|
CREATE TABLE test(a int);
|
|
SELECT create_distributed_table('test','a');
|
|
insert into test values(1);
|
|
|
|
select query, calls from citus_stat_statements();
|
|
\if :server_version_ge_14
|
|
SET compute_query_id = 'off';
|
|
\else
|
|
set citus.stat_statements_track = 'none';
|
|
\endif
|
|
|
|
-- for pg >= 14, since compute_query_id is off, this insert
|
|
-- shouldn't be tracked
|
|
-- for pg < 14, we disable it explicitly so that we don't need
|
|
-- to add an alternative output file.
|
|
insert into test values(1);
|
|
select query, calls from citus_stat_statements();
|
|
|
|
|
|
\if :server_version_ge_14
|
|
SET compute_query_id = 'on';
|
|
\else
|
|
RESET citus.stat_statements_track;
|
|
\endif
|
|
|
|
|
|
SELECT citus_stat_statements_reset();
|
|
|
|
|
|
-- it should now succeed, but with empty result
|
|
SELECT normalize_query_string(query) FROM citus_stat_statements;
|
|
|
|
-- run some queries
|
|
SELECT count(*) FROM lineitem_hash_part;
|
|
SELECT count(*) FROM lineitem_hash_part;
|
|
SELECT l_orderkey FROM lineitem_hash_part;
|
|
SELECT l_orderkey FROM lineitem_hash_part WHERE l_orderkey > 100;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 4;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 4;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 1;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 1200;
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- test GUC citus.stat_statements_track
|
|
SET citus.stat_statements_track TO 'none';
|
|
-- this shouldn't increment the call count since tracking is disabled
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 4;
|
|
-- this should give the same output as above, since the last query is not counted
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
-- reset the GUC to track stats
|
|
SET citus.stat_statements_track TO 'all';
|
|
|
|
-- reset pg_stat_statements and verify it also cleans citus_stat_statements output
|
|
-- verify that entries are actually removed from citus_stat_statements
|
|
SELECT pg_stat_statements_reset();
|
|
SELECT * FROM citus_stat_statements;
|
|
|
|
-- run some queries
|
|
SELECT count(*) FROM lineitem_hash_part;
|
|
SELECT count(*) FROM lineitem_hash_part;
|
|
SELECT l_orderkey FROM lineitem_hash_part;
|
|
SELECT l_orderkey FROM lineitem_hash_part WHERE l_orderkey > 100;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 4;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 4;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 1;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 1200;
|
|
|
|
-- show current list, and reset pg_stat_statements
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
SELECT pg_stat_statements_reset();
|
|
|
|
SELECT count(*) FROM lineitem_hash_part;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 4;
|
|
|
|
-- verify although pg_stat_statements was reset, some call counts are not
|
|
-- if a query is re-issued between pg_stat_statements_reset() and citus_stat_statements()
|
|
-- its call count is preserved.
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
|
|
-- citus_stat_statements_reset() must be called to reset call counts
|
|
SELECT citus_stat_statements_reset();
|
|
|
|
SELECT count(*) FROM lineitem_hash_part;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 4;
|
|
|
|
-- verify citus stats has only 2 rows
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- create test tables to run update/delete scenarios
|
|
CREATE TABLE stat_test_text(user_id text, value int);
|
|
CREATE TABLE stat_test_bigint(user_id bigint, value int);
|
|
|
|
SELECT citus_stat_statements_reset();
|
|
|
|
-- verify regular tables are not included in citus_stat_statements
|
|
SELECT * FROM stat_test_text;
|
|
SELECT * FROM stat_test_bigint WHERE user_id = 1::bigint;
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
SELECT create_distributed_table('stat_test_text', 'user_id');
|
|
SELECT create_distributed_table('stat_test_bigint', 'user_id');
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
SELECT * FROM stat_test_text;
|
|
SELECT * FROM stat_test_text WHERE user_id = 'me';
|
|
|
|
SELECT * FROM stat_test_bigint;
|
|
SELECT * FROM stat_test_bigint WHERE user_id = 2::bigint;
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- insert some rows and check stats
|
|
INSERT INTO stat_test_bigint VALUES (1, 1);
|
|
INSERT INTO stat_test_bigint VALUES (7, 1);
|
|
INSERT INTO stat_test_bigint VALUES (7, 1), (2,3);
|
|
INSERT INTO stat_test_bigint VALUES (8, 1), (8,3);
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- delete some rows and check stats
|
|
SELECT citus_stat_statements_reset();
|
|
|
|
DELETE FROM stat_test_bigint WHERE value > 1000;
|
|
DELETE FROM stat_test_bigint WHERE value > 1200;
|
|
DELETE FROM stat_test_bigint WHERE user_id > 1000;
|
|
DELETE FROM stat_test_bigint WHERE user_id = 1000;
|
|
DELETE FROM stat_test_bigint WHERE user_id = 1000;
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- update some rows and check stats
|
|
SELECT citus_stat_statements_reset();
|
|
|
|
UPDATE stat_test_bigint SET value = 300 WHERE value = 3000;
|
|
UPDATE stat_test_bigint SET value = 320 WHERE value = 3200;
|
|
UPDATE stat_test_bigint SET value = 300 WHERE user_id = 3;
|
|
UPDATE stat_test_bigint SET value = 300 WHERE user_id = 3;
|
|
UPDATE stat_test_bigint SET value = 3000 WHERE user_id > 500;
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- test joins
|
|
CREATE TABLE stat_test_bigint_other(LIKE stat_test_bigint);
|
|
SELECT create_distributed_table('stat_test_bigint_other', 'user_id');
|
|
|
|
SELECT citus_stat_statements_reset();
|
|
|
|
INSERT INTO stat_test_bigint_other SELECT * FROM stat_test_bigint;
|
|
INSERT INTO stat_test_bigint_other SELECT * FROM stat_test_bigint WHERE user_id = 3;
|
|
INSERT INTO stat_test_bigint_other SELECT * FROM stat_test_bigint WHERE user_id = 3;
|
|
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_bigint_other o USING (user_id);
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_bigint_other o USING (user_id);
|
|
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_bigint_other o USING (user_id)
|
|
WHERE b.user_id = 3;
|
|
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_bigint_other o USING (user_id)
|
|
WHERE b.user_id = 3;
|
|
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_bigint_other o USING (user_id)
|
|
WHERE o.user_id = 3;
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- test reference table
|
|
CREATE TABLE stat_test_reference(LIKE stat_test_bigint);
|
|
SELECT create_reference_table('stat_test_reference');
|
|
|
|
INSERT INTO stat_test_reference SELECT user_id, count(*) FROM stat_test_bigint GROUP BY user_id;
|
|
|
|
SELECT citus_stat_statements_reset();
|
|
|
|
SELECT count(*) FROM stat_test_reference;
|
|
SELECT count(*) FROM stat_test_reference WHERE user_id = 2;
|
|
SELECT count(*) FROM stat_test_reference WHERE user_id = 2;
|
|
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_reference r USING (user_id);
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_reference r USING (user_id);
|
|
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_reference r USING (user_id)
|
|
WHERE b.user_id = 1;
|
|
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_reference r USING (user_id)
|
|
WHERE b.user_id = 1 and r.value > 0;
|
|
|
|
SELECT count(*) FROM stat_test_bigint b JOIN stat_test_reference r USING (user_id)
|
|
WHERE r.user_id = 1;
|
|
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- non-stats role should only see its own entries, even when calling citus_query_stats directly
|
|
CREATE USER nostats;
|
|
GRANT SELECT ON TABLE lineitem_hash_part TO nostats;
|
|
|
|
SET ROLE nostats;
|
|
SELECT count(*) FROM lineitem_hash_part WHERE l_orderkey = 2;
|
|
SELECT partition_key FROM citus_query_stats();
|
|
RESET ROLE;
|
|
|
|
-- stats-role/superuser should be able to see entries belonging to other users
|
|
SELECT partition_key FROM citus_query_stats() WHERE partition_key = '2';
|
|
|
|
-- drop pg_stat_statements and verify citus_stat_statement does not work anymore
|
|
DROP extension pg_stat_statements;
|
|
SELECT normalize_query_string(query), executor, partition_key, calls
|
|
FROM citus_stat_statements
|
|
ORDER BY 1, 2, 3, 4;
|
|
|
|
-- drop created tables
|
|
DROP TABLE stat_test_text, stat_test_bigint, stat_test_bigint_other, stat_test_reference;
|
|
|
|
DROP FUNCTION normalize_query_string(text);
|
|
|
|
|
|
\if :server_version_ge_14
|
|
SET compute_query_id = 'off';
|
|
\endif
|