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

TimescaleDB使用time_bucket不支持小于1天的时间间隔问题

TimescaleDB time_bucket函数无法设置小于1天的时间间隔,报错"interval must not have sub-day precision"

在FastAPI中使用TimescaleDB的time_bucket函数时,设置如'15 minutes'这类小于1天的时间间隔会触发错误:interval must not have sub-day precision。当前使用TimescaleDB版本2.16.1,PostgreSQL版本14.12,需求是支持15分钟到1天的时间间隔以生成K线图,希望通过自动配置解决该问题,无需手动网页操作。

相关代码

1. FastAPI异步查询函数

async def get_candlestick_data(self, db: AsyncSession, market_name: str, resource_name: str, interval: str):
    sql = f"""
    SELECT 
        time_bucket('{interval}', timestamp) as period,
        FIRST(price, timestamp) as open,
        MAX(price) as high,
        MIN(price) as low,
        LAST(price, timestamp) as close,
        SUM(quantity) as volume
    FROM 
        resource_market_value
    WHERE
        market_name = :market_name AND resource_name = :resource_name
    GROUP BY 
        period
    ORDER BY 
        period;
    """
    result = await db.execute(text(sql), {'market_name': market_name, 'resource_name': resource_name})
    return result.fetchall()

2. SQLAlchemy模型

from sqlalchemy import DateTime
from sqlalchemy import Column, Integer, String, BigInteger
from common_modules.database.base import Base


class ResourceMarketValue(Base):
    __tablename__ = 'resource_market_value'
    id = Column(BigInteger, primary_key=True, autoincrement=True)
    market_name = Column(String, nullable=False)
    resource_name = Column(String, nullable=False)
    timestamp = Column(DateTime, nullable=False)
    price = Column(Integer, nullable=False)
    quantity = Column(Integer, nullable=False)

3. 创建超表语句

SELECT create_hypertable('resource_market_value', 'timestamp');

错误日志

2024-09-12 14:59:54.455 UTC [50740] ERROR:  interval must not have sub-day precision
2024-09-12 14:59:54.455 UTC [50740] STATEMENT:
                SELECT
                    time_bucket('15 minutes', timestamp) as period,
                    FIRST(price, timestamp) as open,
                    MAX(price) as high,
                    MIN(price) as low,
                    LAST(price, timestamp) as close,
                    SUM(quantity) as volume
                FROM
                    resource_market_value
                WHERE
                    market_name = $1 AND resource_name = $2
                GROUP BY
                    period
                ORDER BY
                    period;

2024-09-12 14:59:54.456 UTC [50741] ERROR:  could not map dynamic shared memory segment
2024-09-12 14:59:54.456 UTC [50742] ERROR:  could not map dynamic shared memory segment
2024-09-12 14:59:54.458 UTC [1] LOG:  background worker "parallel worker" (PID 50741) exited with exit code 1
2024-09-12 14:59:54.459 UTC [1] LOG:  background worker "parallel worker" (PID 50742) exited with exit code 1

解决方案

1. 调整超表的chunk_time_interval

报错核心原因是创建超表时默认chunk_time_interval为1天,当time_bucket间隔小于该值时,并行聚合会触发限制。修改创建超表语句,显式设置更小的时间间隔(比如1小时,适配15分钟的聚合需求):

SELECT create_hypertable('resource_market_value', 'timestamp', chunk_time_interval => INTERVAL '1 hour');

如果已创建超表,可通过以下语句修改现有超表的chunk间隔:

SELECT set_chunk_time_interval('resource_market_value', INTERVAL '1 hour');

2. 修复SQL注入风险

原代码用f-string直接拼接interval参数存在SQL注入风险,改为参数化查询:

async def get_candlestick_data(self, db: AsyncSession, market_name: str, resource_name: str, interval: str):
    sql = """
    SELECT 
        time_bucket(:interval, timestamp) as period,
        FIRST(price, timestamp) as open,
        MAX(price) as high,
        MIN(price) as low,
        LAST(price, timestamp) as close,
        SUM(quantity) as volume
    FROM 
        resource_market_value
    WHERE
        market_name = :market_name AND resource_name = :resource_name
    GROUP BY 
        period
    ORDER BY 
        period;
    """
    result = await db.execute(text(sql), {'market_name': market_name, 'resource_name': resource_name, 'interval': interval})
    return result.fetchall()

3. 可选:调整PostgreSQL动态共享内存配置

错误日志中出现的could not map dynamic shared memory segment可能影响并行查询,可修改PostgreSQL配置文件(postgresql.conf)中的相关参数:

dynamic_shared_memory_type = posix  # 或根据系统选择合适的类型
max_parallel_workers_per_gather = 4  # 调整并行worker数量

修改后重启PostgreSQL服务即可。

内容的提问来源于stack exchange,提问作者Matthieu Raynaud de Fitte

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:47:09