如何避免PostgreSQL访问特定归档chunk?函数报错求助
问题描述
我需要在不修复缺失或损坏chunk的前提下解决问题,我不负责维护数据库,已知旧chunk归档在NAS而非生产SSD,出于磁盘损耗和性能考虑,不希望函数访问这些旧chunk。
当前自定义PL/pgSQL函数CTO_pec运行时报错:
ERROR: could not open file "pg_tblspc/16400/PG_14_202107181/17549/134380077": No such file or directory
CONTEXT: PL/pgSQL assignment "temperatura := (SELECT value FROM kepware_messages WHERE tag_id = 94824 AND "timestamp" >= timestamp_from - 1209600000 AND "timestamp" <= item.timestamp ORDER BY "timestamp" DESC LIMIT 1)"
PL/pgSQL function cto_pec(bigint,bigint) line 28 at assignment
其中-1209600000是将查询范围限制为所选时间范围前2周,经查询该缺失文件不在此时间范围内。但直接使用item.value的简化版函数在相同时间范围下可正常运行。
我想知道:
- PostgreSQL为何会访问不在查询范围内的chunk?
- 如何限制这种访问,避免函数因无关chunk报错?
报错函数代码
CREATE OR REPLACE FUNCTION CTO_pec(timestamp_from bigint, timestamp_to bigint) RETURNS TABLE (cas bigint, ciljna_temp decimal) AS $$ DECLARE temperatura decimal; item record; last_item_temperatura decimal; BEGIN CREATE TEMPORARY TABLE IF NOT EXISTS myTempTable( time bigint, ciljna_temp decimal ); -- 使用UNION在图表起始位置绘制线条 FOR item IN (SELECT CAST(value AS integer), timestamp FROM kepware_messages WHERE tag_id = 94828 AND timestamp >= timestamp_from AND timestamp <= timestamp_to UNION (SELECT CAST(value AS integer), timestamp_from AS "timestamp" FROM kepware_messages WHERE tag_id = 94828 AND timestamp >= timestamp_from - 1209600000 AND timestamp <= timestamp_from ORDER BY "timestamp" DESC LIMIT 1)) LOOP CASE item.value WHEN 1 THEN temperatura := (SELECT value FROM kepware_messages WHERE tag_id = 94816 AND "timestamp" >= timestamp_from - 1209600000 AND "timestamp" <= item.timestamp ORDER BY "timestamp" DESC LIMIT 1); WHEN 2 THEN temperatura := (SELECT value FROM kepware_messages WHERE tag_id = 94818 AND "timestamp" >= timestamp_from - 1209600000 AND "timestamp" <= item.timestamp ORDER BY "timestamp" DESC LIMIT 1); WHEN 3 THEN temperatura := (SELECT value FROM kepware_messages WHERE tag_id = 94820 AND "timestamp" >= timestamp_from - 1209600000 AND "timestamp" <= item.timestamp ORDER BY "timestamp" DESC LIMIT 1); WHEN 4 THEN temperatura := (SELECT value FROM kepware_messages WHERE tag_id = 94822 AND "timestamp" >= timestamp_from - 1209600000 AND "timestamp" <= item.timestamp ORDER BY "timestamp" DESC LIMIT 1); WHEN 5 THEN temperatura := (SELECT value FROM kepware_messages WHERE tag_id = 94824 AND "timestamp" >= timestamp_from - 1209600000 AND "timestamp" <= item.timestamp ORDER BY "timestamp" DESC LIMIT 1); WHEN 6 THEN temperatura := (SELECT value FROM kepware_messages WHERE tag_id = 94826 AND "timestamp" >= timestamp_from - 1209600000 AND "timestamp" <= item.timestamp ORDER BY "timestamp" DESC LIMIT 1); END CASE; last_item_temperatura := temperatura; INSERT INTO myTempTable VALUES (item.timestamp, temperatura); END LOOP; INSERT INTO myTempTable VALUES (timestamp_to, last_item_temperatura); RETURN QUERY SELECT * FROM myTempTable; DROP TABLE IF EXISTS myTempTable; END; $$ LANGUAGE plpgsql;
正常运行的简化版函数代码
CREATE OR REPLACE FUNCTION CTO_pec(timestamp_from bigint, timestamp_to bigint) RETURNS TABLE (cas bigint, ciljna_temp decimal) AS $$ DECLARE temperatura decimal; item record; last_item_temperatura decimal; BEGIN CREATE TEMPORARY TABLE IF NOT EXISTS myTempTable( time bigint, ciljna_temp decimal ); -- 使用UNION在图表起始位置绘制线条 FOR item IN (SELECT CAST(value AS integer), timestamp FROM kepware_messages WHERE tag_id = 94828 AND timestamp >= timestamp_from AND timestamp <= timestamp_to UNION (SELECT CAST(value AS integer), timestamp_from AS "timestamp" FROM kepware_messages WHERE tag_id = 94828 AND timestamp >= timestamp_from - 1209600000 AND timestamp <= timestamp_from ORDER BY "timestamp" DESC LIMIT 1)) LOOP last_item_temperatura := item.value; INSERT INTO myTempTable VALUES (item.timestamp, item.value); RAISE NOTICE '%, %', item.value, item.timestamp; END LOOP; INSERT INTO myTempTable VALUES (timestamp_to, last_item_temperatura); RETURN QUERY SELECT * FROM myTempTable; DROP TABLE IF EXISTS myTempTable; END; $$ LANGUAGE plpgsql;
内容的提问来源于stack exchange,提问作者Xr2206
相关产品推荐
相关产品推荐

