You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:44:58