SELECT *
FROM public.admin_get_sales_data(1, 5000,
null, null, null, null,
null, null, null)
使用不同的第一个参数 1,2,3... 调用此函数,它会在任何随机执行 5 或 6 次时失败。这个问题的原因和解决办法是什么?
第五次尝试长时间执行查询后出现错误消息。
用户查询可能需要查看必须删除的行版本。由于与恢复冲突而取消语句
这是函数体:
CREATE OR REPLACE FUNCTION public.admin_get_sales_data(
page_num integer,
page_size integer,
filter_market_id integer,
filter_partner_id integer,
filter_order_rating integer[],
filter_display_id_pattern text,
filter_date_range text,
start_date timestamp with time zone,
end_date timestamp with time zone)
RETURNS TABLE(id integer, display_id character, customer_name text, partner_name character varying, partner_id integer, total_amount numeric, created_at timestamp with time zone, updated_at timestamp with time zone, items text, market_id integer, market_name character varying, order_status character varying, order_rating smallint, review text, bag_created_times timestamp without time zone[], surplus_discount_percentage numeric, deal_discount_percentage numeric, timezone_name character varying)
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
BEGIN
RETURN QUERY
WITH bag_counts AS (
SELECT
bl.partner_id,
bl.order_id,
bl.bag_type,
bl.bag_price,
bl.retail_price,
COUNT(*) AS bag_count
FROM
bags_listing bl
GROUP BY
bl.partner_id,
bl.order_id,
bl.bag_type,
bl.bag_price,
bl.retail_price
),
cancelled_bag_counts AS (
SELECT
bl.partner_id,
clbl.order_id,
bl.bag_type,
bl.bag_price,
bl.retail_price,
COUNT(*) AS bag_count
FROM
bags_listing bl
JOIN cancelled_order_bags_listing_map clbl ON bl.id = clbl.bag_listing_id
GROUP BY
bl.partner_id,
clbl.order_id,
bl.bag_type,
bl.bag_price,
bl.retail_price
)
SELECT
od.id,
od.display_id,
CONCAT(cust.first_name, ' ', cust.last_name) AS customer_name,
pt.shop_name AS partner_name,
pt.id AS partner_id,
od.total_amount AS total_amount,
od.created_at,
od.updated_at,
CASE
WHEN od.order_status = 'CANCELLED' THEN (
CASE
WHEN COALESCE(cbc_big.bag_count, 0) > 0 THEN CONCAT(COALESCE(cbc_big.bag_count, 0), 'x Big bag')
ELSE ''
END ||
CASE
WHEN COALESCE(cbc_small.bag_count, 0) > 0 THEN CONCAT(CASE WHEN COALESCE(cbc_big.bag_count, 0) > 0 THEN ', ' ELSE '' END, COALESCE(cbc_small.bag_count, 0), 'x Small bag')
ELSE ''
END ||
CASE
WHEN COALESCE(cbc_deal.bag_count, 0) > 0 THEN CONCAT(CASE WHEN COALESCE(cbc_big.bag_count, 0) > 0 OR COALESCE(cbc_small.bag_count, 0) > 0 THEN ', ' ELSE '' END, COALESCE(cbc_deal.bag_count, 0), 'x Deal bag')
WHEN cbc_big.bag_count IS NOT NULL THEN ''
WHEN cbc_small.bag_count IS NOT NULL THEN ''
ELSE 'NA'
END
)
ELSE (
CASE
WHEN COALESCE(bc_big.bag_count, 0) > 0 THEN CONCAT(COALESCE(bc_big.bag_count, 0), 'x Big bag')
ELSE ''
END ||
CASE
WHEN COALESCE(bc_small.bag_count, 0) > 0 THEN CONCAT(CASE WHEN COALESCE(bc_big.bag_count, 0) > 0 THEN ', ' ELSE '' END, COALESCE(bc_small.bag_count, 0), 'x Small bag')
ELSE ''
END ||
CASE
WHEN COALESCE(bc_deal.bag_count, 0) > 0 THEN CONCAT(CASE WHEN COALESCE(bc_big.bag_count, 0) > 0 OR COALESCE(bc_small.bag_count, 0) > 0 THEN ', ' ELSE '' END, COALESCE(bc_deal.bag_count, 0), 'x Deal bag')
WHEN bc_big.bag_count IS NOT NULL THEN ''
WHEN bc_small.bag_count IS NOT NULL THEN ''
ELSE 'NA'
END
)
END AS items,
pt.market_id AS market_id,
mt.market_name,
od.order_status,
pr.rating AS order_rating,
pr.comment AS review,
CASE
WHEN od.order_status = 'CANCELLED' THEN (
SELECT ARRAY(
SELECT
CASE
WHEN pt.utc_minutes_offset IS NOT NULL
THEN bl.created_at AT TIME ZONE 'UTC' + INTERVAL '1 minute' * pt.utc_minutes_offset
ELSE bl.created_at::timestamp without time zone
END
FROM bags_listing bl
JOIN cancelled_order_bags_listing_map clbl ON bl.id = clbl.bag_listing_id
WHERE clbl.order_id = od.id
ORDER BY bl.created_at
)
)
ELSE (
SELECT ARRAY(
SELECT
CASE
WHEN pt.utc_minutes_offset IS NOT NULL
THEN bl.created_at AT TIME ZONE 'UTC' + INTERVAL '1 minute' * pt.utc_minutes_offset
ELSE bl.created_at::timestamp without time zone
END
FROM bags_listing bl
WHERE bl.order_id = od.id
ORDER BY bl.created_at
)
)
END AS bag_created_times,
CASE
WHEN COALESCE(bc_big.bag_count, 0) > 0
OR COALESCE(cbc_big.bag_count, 0) > 0
OR COALESCE(bc_small.bag_count, 0) > 0
OR COALESCE(cbc_small.bag_count, 0) > 0
THEN 66.67
ELSE 0.00
END AS surplus_discount_percentage,
CASE
WHEN COALESCE(bc_deal.bag_count, 0) > 0 OR COALESCE(cbc_deal.bag_count, 0) > 0 THEN
ROUND(
(
GREATEST(COALESCE(bc_deal.retail_price, 0), COALESCE(cbc_deal.retail_price, 0)) -
GREATEST(COALESCE(bc_deal.bag_price, 0), COALESCE(cbc_deal.bag_price, 0))
) /
GREATEST(COALESCE(bc_deal.retail_price, 0), COALESCE(cbc_deal.retail_price, 0)) * 100,
2
)
ELSE
0.00
END AS deal_discount_percentage,
pt.timezone_name
FROM
public.orders od
JOIN
public.customers cust ON od.customer_id = cust.id
JOIN
public.partners pt ON od.partner_id = pt.id
LEFT JOIN bag_counts bc_big ON od.partner_id = bc_big.partner_id AND od.id = bc_big.order_id AND bc_big.bag_type = 1
LEFT JOIN bag_counts bc_small ON od.partner_id = bc_small.partner_id AND od.id = bc_small.order_id AND bc_small.bag_type = 2
LEFT JOIN bag_counts bc_deal ON od.partner_id = bc_deal.partner_id AND od.id = bc_deal.order_id AND bc_deal.bag_type = 3
LEFT JOIN cancelled_bag_counts cbc_big ON od.partner_id = cbc_big.partner_id AND od.id = cbc_big.order_id AND cbc_big.bag_type = 1
LEFT JOIN cancelled_bag_counts cbc_small ON od.partner_id = cbc_small.partner_id AND od.id = cbc_small.order_id AND cbc_small.bag_type = 2
LEFT JOIN cancelled_bag_counts cbc_deal ON od.partner_id = cbc_deal.partner_id AND od.id = cbc_deal.order_id AND cbc_deal.bag_type = 3
JOIN
markets mt ON pt.market_id = mt.id
LEFT JOIN (
SELECT
order_id,
rating,
comment
FROM
partner_ratings
GROUP BY
order_id,
rating,
comment
) pr ON od.id = pr.order_id
WHERE
od.order_status IN ('COMPLETED', 'CONFIRMED', 'CANCELLED', 'REFUNDED')
AND (filter_market_id IS NULL OR pt.market_id = filter_market_id)
AND (filter_partner_id IS NULL OR pt.id = filter_partner_id)
AND (filter_display_id_pattern IS NULL OR od.display_id ILIKE '%' || filter_display_id_pattern || '%') -- Apply the display_id filter
AND (
CASE
WHEN filter_date_range = 'All Time' THEN true
WHEN filter_date_range = 'This Month' THEN DATE_TRUNC('month', od.created_at) = DATE_TRUNC('month', CURRENT_TIMESTAMP)
WHEN filter_date_range = 'Today' THEN od.created_at::date = CURRENT_DATE
WHEN filter_date_range = 'Custom' THEN od.created_at BETWEEN start_date AND end_date
ELSE true
END
)
-- Apply the filter_order_rating
AND (filter_order_rating IS NULL OR pr.rating = ANY(filter_order_rating))
ORDER BY
od.created_at DESC
LIMIT
page_size
OFFSET
(page_num - 1) * page_size;
END;
$BODY$;
我们需要在此功能中解决这个问题
您可以通过增加 max_standby_streaming_delay 为查询提供更长的宽限期。 这样做会带来一些后果,您可能认为可以接受,也可能不认为可以接受。您还可以查看 hot_standby_feedback。
如果没有充分的理由说明为什么查询首先应该很慢,那么您可以尝试使其更快,这样就不会与这些延迟发生冲突。将查询从函数中取出并使用
EXPLAIN (ANALYZE, BUFFERS)
执行它,看看为什么它很慢。 如果它可以预见地在执行一定次数后发生,那么也许 plan_cache_mode = force_custom_plan 会有所帮助,但你也说是随机的,所以谁知道呢。
最后,您可以只在主服务器上查询,而不是在副本服务器上。