Postgres - 获取分配给变量的查询成本
Postgres - Get the query cost assign to a variable
要获取查询的estimated cost
,我使用EXPLAIN SELECT column FROM table;
,要获取查询的current cost
,我使用EXPLAIN ANALYSE SELECT column FROM table;
,我的问题是如何自动获取查询的 cost
,而无需手动为每个查询 运行 explain
。
我需要这样的东西:
DECLARE cost integer;
DECLARE highercost integer;
DECLARE query text;
highercost := 0;
i := 0;
query = '';
WHILE i < array_length( queryarray ,1) LOOP
cost := explain analyse queryarray[i];
IF cost > highercost THEN
highercost := cost;
query := queryarray[i];
END IF;
i := i+1;
END LOOP;
想法是创建一个脚本来检查 log
中的查询和 psql
中的 运行 查询,或者将 log
查询复制到 [=41] =] 和 运行 与 plain SQL
来验证最昂贵的,目前正是我所寻求的,无需担心真正的 cost
查询 ( "cost" X "times executed per minute"),INSERT
、UPDATE
和 DELETE
的成本等。
我希望这是可能的,如果不能,还有另一种方法可以搜索昂贵的查询而不用逐一检查吗?
编辑:
忘了说,我用的是 Postgres 9.1。
也许您可以创建一个类似于以下的函数:
CREATE OR REPLACE FUNCTION query_cost(
queries text[],
query OUT text, cost OUT float8, duration OUT float8
) RETURNS SETOF record LANGUAGE plpgsql STRICT AS
$$DECLARE
i integer;
p json;
BEGIN
/* loop through input queries */
FOR i IN array_lower(queries, 1)..array_upper(queries, 1) LOOP
query := queries[i];
/* get execution plan in JSON */
EXECUTE 'EXPLAIN (ANALYZE, FORMAT JSON) ' || query INTO p;
/* extract total cost and execution time */
SELECT p->0->'Plan'->>'Total Cost',
p->0->'Plan'->>'Actual Total Time'
INTO cost, duration;
/* return query, cost and duration */
RETURN NEXT;
END LOOP;
END;$$;
你可以这样使用它:
SELECT *
FROM query_cost(
ARRAY[
'SELECT 42',
'SELECT count(*) FROM large'
]
)
ORDER BY duration DESC;
┌────────────────────────────┬─────────┬──────────┐
│ query │ cost │ duration │
├────────────────────────────┼─────────┼──────────┤
│ SELECT count(*) FROM large │ 1693.01 │ 150.171 │
│ SELECT 42 │ 0.01 │ 0.002 │
└────────────────────────────┴─────────┴──────────┘
(2 rows)
基于这个答案 [https://pt.whosebug.com/questions/155113][1] :
CREATE or REPLACE function custo_consulta(_consulta text[])
returns table (consulta text, custo_execucao numeric, tempo_execucao numeric ) as '
declare custo text;
begin
foreach consulta in array _consulta loop
execute ''EXPLAIN ( FORMAT JSON, ANALYZE ) '' || consulta INTO custo;
custo_execucao := split_part(split_part(custo, ''"Total Cost": '', 2), '','', 1);
tempo_execucao := split_part(split_part(custo, ''"Actual Total Time": '', 2), '','', 1);
return next;
end loop;
end;
' language plpgsql;
SELECT *
FROM custo_consulta(array['SELECT COUNT(*) FROM syo_evento WHERE id_grupoevento = ''OPORTUNIDADE''', 'SELECT COUNT(*) FROM syo_evento WHERE id_grupoevento = ''REVISAO'''])
ORDER BY custo_execucao desc;
结果
consulta custo_execucao tempo_execucao
SELECT COUNT(*) FROM syo_evento WHERE id_grupoevento = 'REVISAO' 38426,44 128,267
SELECT COUNT(*) FROM syo_evento WHERE id_grupoevento = 'OPORTUNIDADE' 38252,65 123,996
只是另一个问题,我在使用 $$ 时收到错误消息,但这将得到解决。
要获取查询的estimated cost
,我使用EXPLAIN SELECT column FROM table;
,要获取查询的current cost
,我使用EXPLAIN ANALYSE SELECT column FROM table;
,我的问题是如何自动获取查询的 cost
,而无需手动为每个查询 运行 explain
。
我需要这样的东西:
DECLARE cost integer;
DECLARE highercost integer;
DECLARE query text;
highercost := 0;
i := 0;
query = '';
WHILE i < array_length( queryarray ,1) LOOP
cost := explain analyse queryarray[i];
IF cost > highercost THEN
highercost := cost;
query := queryarray[i];
END IF;
i := i+1;
END LOOP;
想法是创建一个脚本来检查 log
中的查询和 psql
中的 运行 查询,或者将 log
查询复制到 [=41] =] 和 运行 与 plain SQL
来验证最昂贵的,目前正是我所寻求的,无需担心真正的 cost
查询 ( "cost" X "times executed per minute"),INSERT
、UPDATE
和 DELETE
的成本等。
我希望这是可能的,如果不能,还有另一种方法可以搜索昂贵的查询而不用逐一检查吗?
编辑:
忘了说,我用的是 Postgres 9.1。
也许您可以创建一个类似于以下的函数:
CREATE OR REPLACE FUNCTION query_cost(
queries text[],
query OUT text, cost OUT float8, duration OUT float8
) RETURNS SETOF record LANGUAGE plpgsql STRICT AS
$$DECLARE
i integer;
p json;
BEGIN
/* loop through input queries */
FOR i IN array_lower(queries, 1)..array_upper(queries, 1) LOOP
query := queries[i];
/* get execution plan in JSON */
EXECUTE 'EXPLAIN (ANALYZE, FORMAT JSON) ' || query INTO p;
/* extract total cost and execution time */
SELECT p->0->'Plan'->>'Total Cost',
p->0->'Plan'->>'Actual Total Time'
INTO cost, duration;
/* return query, cost and duration */
RETURN NEXT;
END LOOP;
END;$$;
你可以这样使用它:
SELECT *
FROM query_cost(
ARRAY[
'SELECT 42',
'SELECT count(*) FROM large'
]
)
ORDER BY duration DESC;
┌────────────────────────────┬─────────┬──────────┐
│ query │ cost │ duration │
├────────────────────────────┼─────────┼──────────┤
│ SELECT count(*) FROM large │ 1693.01 │ 150.171 │
│ SELECT 42 │ 0.01 │ 0.002 │
└────────────────────────────┴─────────┴──────────┘
(2 rows)
基于这个答案 [https://pt.whosebug.com/questions/155113][1] :
CREATE or REPLACE function custo_consulta(_consulta text[])
returns table (consulta text, custo_execucao numeric, tempo_execucao numeric ) as '
declare custo text;
begin
foreach consulta in array _consulta loop
execute ''EXPLAIN ( FORMAT JSON, ANALYZE ) '' || consulta INTO custo;
custo_execucao := split_part(split_part(custo, ''"Total Cost": '', 2), '','', 1);
tempo_execucao := split_part(split_part(custo, ''"Actual Total Time": '', 2), '','', 1);
return next;
end loop;
end;
' language plpgsql;
SELECT *
FROM custo_consulta(array['SELECT COUNT(*) FROM syo_evento WHERE id_grupoevento = ''OPORTUNIDADE''', 'SELECT COUNT(*) FROM syo_evento WHERE id_grupoevento = ''REVISAO'''])
ORDER BY custo_execucao desc;
结果
consulta custo_execucao tempo_execucao
SELECT COUNT(*) FROM syo_evento WHERE id_grupoevento = 'REVISAO' 38426,44 128,267
SELECT COUNT(*) FROM syo_evento WHERE id_grupoevento = 'OPORTUNIDADE' 38252,65 123,996
只是另一个问题,我在使用 $$ 时收到错误消息,但这将得到解决。