From 1bea67979724d7ab1f9edf6936582cc033a8a487 Mon Sep 17 00:00:00 2001 From: TinyBag Date: Mon, 19 Aug 2024 10:21:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=85=A2sql=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E6=94=B6=E9=9B=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../instruments/statement/instr_statement.cpp | 3 +- src/gausskernel/process/tcop/pquery.cpp | 2 + .../runtime/executor/functions.cpp | 2 + src/include/executor/exec/execdesc.h | 1 + src/test/regress/expected/function.out | 77 +++++++++++++++++++ src/test/regress/sql/function.sql | 47 ++++++++++- 6 files changed, 130 insertions(+), 2 deletions(-) diff --git a/src/gausskernel/cbb/instruments/statement/instr_statement.cpp b/src/gausskernel/cbb/instruments/statement/instr_statement.cpp index 6479ac1e2..8d83ae84a 100755 --- a/src/gausskernel/cbb/instruments/statement/instr_statement.cpp +++ b/src/gausskernel/cbb/instruments/statement/instr_statement.cpp @@ -2309,7 +2309,8 @@ void instr_stmt_report_query_plan(QueryDesc *queryDesc) StatementStatContext *ssctx = (StatementStatContext *)u_sess->statement_cxt.curStatementMetrics; if (queryDesc == NULL || ssctx == NULL || ssctx->level > STMT_TRACK_L2 || (ssctx->plan_size != 0 && !u_sess->unique_sql_cxt.is_open_cursor) - || (u_sess->statement_cxt.executer_run_level > 1 && !IS_UNIQUE_SQL_TRACK_ALL)) { + || (u_sess->statement_cxt.executer_run_level > 1 && !IS_UNIQUE_SQL_TRACK_ALL) + || queryDesc->for_simplify_func) { return; } /* when getting plan directly from CN, the plan is partial, deparse plan will be failed, diff --git a/src/gausskernel/process/tcop/pquery.cpp b/src/gausskernel/process/tcop/pquery.cpp index 15cbfe536..ddbe19288 100644 --- a/src/gausskernel/process/tcop/pquery.cpp +++ b/src/gausskernel/process/tcop/pquery.cpp @@ -106,6 +106,7 @@ QueryDesc* CreateQueryDesc(PlannedStmt* plannedstmt, const char* sourceText, Sna qd->planstate = NULL; qd->totaltime = NULL; qd->executed = false; + qd->for_simplify_func = false; #ifdef ENABLE_MOT if (motJitContext != nullptr && JitExec::IsJitContextValid(motJitContext)) { qd->mot_jit_context = motJitContext; @@ -141,6 +142,7 @@ QueryDesc* CreateUtilityQueryDesc( qd->planstate = NULL; qd->totaltime = NULL; qd->executed = false; + qd->for_simplify_func = false; #ifdef ENABLE_MOT qd->mot_jit_context = nullptr; #endif diff --git a/src/gausskernel/runtime/executor/functions.cpp b/src/gausskernel/runtime/executor/functions.cpp index 3bd71ea38..aeee3c95d 100644 --- a/src/gausskernel/runtime/executor/functions.cpp +++ b/src/gausskernel/runtime/executor/functions.cpp @@ -798,6 +798,8 @@ static void postquel_start(execution_state* es, SQLFunctionCachePtr fcache) es->qd = CreateUtilityQueryDesc(es->stmt, fcache->src, GetActiveSnapshot(), dest, fcache->paramLI); } + es->qd->for_simplify_func = true; + /* Utility commands don't need Executor. */ if (es->qd->utilitystmt == NULL) { /* diff --git a/src/include/executor/exec/execdesc.h b/src/include/executor/exec/execdesc.h index 9bc73b8ed..92823ab91 100644 --- a/src/include/executor/exec/execdesc.h +++ b/src/include/executor/exec/execdesc.h @@ -57,6 +57,7 @@ typedef struct QueryDesc { /* This is always set NULL by the core system, but plugins can change it */ struct Instrumentation* totaltime; /* total time spent in ExecutorRun */ bool executed; /* if the query already executed */ + bool for_simplify_func; /* if the query is for simplify function, skip reporting query plan */ #ifdef ENABLE_MOT JitExec::MotJitContext* mot_jit_context; /* MOT JIT context required for executing LLVM jitted code */ #endif diff --git a/src/test/regress/expected/function.out b/src/test/regress/expected/function.out index bdbd7339a..596861c67 100644 --- a/src/test/regress/expected/function.out +++ b/src/test/regress/expected/function.out @@ -2130,3 +2130,80 @@ CONTEXT: referenced column: turn_on SQL statement "select dbe_pldebugger.turn_on(funcoid)" PL/pgSQL function inline_code_block line 7 at SQL statement drop function test_debug1; +\c postgres +alter system set enable_stmt_track=on; +set log_min_duration_statement=0; +set track_stmt_stat_level='L1,L1'; +alter system set instr_unique_sql_count = 10000; +delete from dbe_perf.statement_history; +CREATE TABLE stmt_hist_t1 ( first_name text, last_name text, job_id int, department_id int,d1 bigint ) ; +create index stmt_hist_t1_i1 on stmt_hist_t1 (job_id) ; +create index stmt_hist_t1_i2 on stmt_hist_t1 (department_id) ; +insert into stmt_hist_t1 (first_name,last_name,job_id,department_id) values('Alice', 'Adams', 2, 1 ); +insert into stmt_hist_t1 (first_name,last_name,job_id,department_id) values('Beatrice', 'Brand', 3, 1); +CREATE TABLE stmt_hist_t2 ( job_title text, job_id int) ; +insert into stmt_hist_t2 values( 'Job1', 1 ); +insert into stmt_hist_t2 values( 'Job2', 2 ); +insert into stmt_hist_t2 values( 'Job3', 3 ); +analyze stmt_hist_t1; +analyze stmt_hist_t2; +CREATE FUNCTION func_add_sql() RETURNS integer +AS 'select 3;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; +explain (verbose, costs off) select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 ); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop + Output: 3 + Join Filter: (public.stmt_hist_t1.job_id = stmt_hist_t2.job_id) + -> Nested Loop Anti Join + Output: public.stmt_hist_t1.job_id + Join Filter: ((public.stmt_hist_t1.job_id = public.stmt_hist_t1.department_id) OR (public.stmt_hist_t1.job_id IS NULL) OR (public.stmt_hist_t1.department_id IS NULL)) + -> Seq Scan on public.stmt_hist_t1 + Output: public.stmt_hist_t1.first_name, public.stmt_hist_t1.last_name, public.stmt_hist_t1.job_id, public.stmt_hist_t1.department_id, public.stmt_hist_t1.d1 + -> Materialize + Output: public.stmt_hist_t1.department_id + -> Seq Scan on public.stmt_hist_t1 + Output: public.stmt_hist_t1.department_id + -> Seq Scan on public.stmt_hist_t2 + Output: stmt_hist_t2.job_title, stmt_hist_t2.job_id +(14 rows) + +select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 ); + func_add_sql +-------------- + 3 + 3 +(2 rows) + +call pg_sleep(1); + pg_sleep +---------- + +(1 row) + +select query_plan from dbe_perf.statement_history where query ilike '%select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 );%'; + query_plan +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Datanode Name: datanode1 + + Nested Loop (cost=0.00..3.16 rows=1 width=0) + + Join Filter: (public.stmt_hist_t1.job_id = stmt_hist_t2.job_id) + + -> Nested Loop Anti Join (cost=0.00..2.10 rows=1 width=4) + + Join Filter: ((public.stmt_hist_t1.job_id = public.stmt_hist_t1.department_id) OR (public.stmt_hist_t1.job_id IS NULL) OR (public.stmt_hist_t1.department_id IS NULL))+ + -> Seq Scan on stmt_hist_t1 (cost=0.00..1.02 rows=2 width=4) + + -> Materialize (cost=0.00..1.03 rows=2 width=4) + + -> Seq Scan on stmt_hist_t1 (cost=0.00..1.02 rows=2 width=4) + + -> Seq Scan on stmt_hist_t2 (cost=0.00..1.03 rows=3 width=4) + + + + +(1 row) + +drop table stmt_hist_t1, stmt_hist_t2 cascade; +drop function func_add_sql; +alter system set enable_stmt_track=off; +reset log_min_duration_statement; +reset track_stmt_stat_level; +alter system set instr_unique_sql_count = 100; +\c regression diff --git a/src/test/regress/sql/function.sql b/src/test/regress/sql/function.sql index ab5095f6b..e6728d1d8 100644 --- a/src/test/regress/sql/function.sql +++ b/src/test/regress/sql/function.sql @@ -1153,4 +1153,49 @@ begin end; $$; -drop function test_debug1; \ No newline at end of file +drop function test_debug1; + +\c postgres + +alter system set enable_stmt_track=on; +set log_min_duration_statement=0; +set track_stmt_stat_level='L1,L1'; +alter system set instr_unique_sql_count = 10000; +delete from dbe_perf.statement_history; + +CREATE TABLE stmt_hist_t1 ( first_name text, last_name text, job_id int, department_id int,d1 bigint ) ; +create index stmt_hist_t1_i1 on stmt_hist_t1 (job_id) ; +create index stmt_hist_t1_i2 on stmt_hist_t1 (department_id) ; +insert into stmt_hist_t1 (first_name,last_name,job_id,department_id) values('Alice', 'Adams', 2, 1 ); +insert into stmt_hist_t1 (first_name,last_name,job_id,department_id) values('Beatrice', 'Brand', 3, 1); + +CREATE TABLE stmt_hist_t2 ( job_title text, job_id int) ; +insert into stmt_hist_t2 values( 'Job1', 1 ); +insert into stmt_hist_t2 values( 'Job2', 2 ); +insert into stmt_hist_t2 values( 'Job3', 3 ); + +analyze stmt_hist_t1; +analyze stmt_hist_t2; + +CREATE FUNCTION func_add_sql() RETURNS integer +AS 'select 3;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; + +explain (verbose, costs off) select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 ); +select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 ); + +call pg_sleep(1); + +select query_plan from dbe_perf.statement_history where query ilike '%select func_add_sql() from stmt_hist_t2 join stmt_hist_t1 on stmt_hist_t2.job_id = stmt_hist_t1.job_id where stmt_hist_t1.job_id not in (select department_id from stmt_hist_t1 );%'; + +drop table stmt_hist_t1, stmt_hist_t2 cascade; +drop function func_add_sql; + +alter system set enable_stmt_track=off; +reset log_min_duration_statement; +reset track_stmt_stat_level; +alter system set instr_unique_sql_count = 100; + +\c regression