我有一个名为
new_schema
的模式,其中包含一个表 result
。该表有很多具有继承性的子表,命名为result_23
、result_45
等
我有 35 亿行,数据库运行缓慢。其中一行有一个名为
new_date
的时间戳字段。这从“2022-01-01”开始。我想删除 2023-11-01 之前的所有行。
从父表中删除耗时太长。我尝试直接在 SP 中删除子表,使用
postgres
超级用户执行。如果有什么事情,我可以稍后继续工作。
CREATE OR REPLACE FUNCTION new_schema.delete_old_rows()
RETURNS TABLE (child_table text)
LANGUAGE plpgsql
AS $function$
DECLARE
child_table text;
sql_query text;
BEGIN
FOR child_table IN
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'new_schema'
AND table_name LIKE 'result_%'
loop
sql_query := 'DELETE FROM new_schema.' || child_table || ' WHERE new_date < ''2023-11-01'';';
EXECUTE consulta_sql;
RAISE NOTICE 'Data deleted in table: %', child_table;
END LOOP;
END
$function$;
我
DELETE
从每个子表循环,它似乎工作(尽管对于大表需要很长时间)。但当我用SELECT
检查时,2022年的数据仍然存在。
打印查询字符串时,
DELETE
看起来很完美:
上下文:SQL 语句“DELETE FROM new_schema.result_26 新日期在哪里 < '2023-11-01';"
我尝试在每个
COMMIT
之后应用 DELETE
,但这不起作用。
PROCEDURE
而不是 FUNCTION
。在那里你可以发出COMMIT
。参见:
可以像这样工作:
CREATE OR REPLACE PROCEDURE new_schema.delete_old_rows() -- !!!
-- no RETURNS clause -- !!!
LANGUAGE plpgsql AS
$func$
DECLARE
_child text;
_row_ct int;
BEGIN
FOR _child IN
SELECT quote_ident(table_name) -- !!!
FROM information_schema.tables
WHERE table_schema = 'new_schema'
AND table_name LIKE 'result_%'
LOOP
EXECUTE 'DELETE FROM new_schema.' || _child || ' WHERE new_date < ''2023-11-01''';
GET DIAGNOSTICS _row_ct = ROW_COUNT;
COMMIT; -- !!!
RAISE NOTICE '% rows deleted from table: %', _row_ct, _child;
END LOOP;
END
$func$;
CALL
执行(重要!):
CALL new_schema.delete_old_rows();
另请注意,您的原始版本容易受到 SQL 注入 攻击。标识符必须被视为动态 SQL 中的用户输入。参见:
您混淆了变量名称:
consulta_sql
与 sql_query
。我简化了。