2

#错误描述: 如果在创建表时定义了外键,则可以将具有外键的表创建到超表中

#为了重现,有下一张表:

CREATE TABLE ids ( 
    measurement_id int DEFAULT 0,        
    description text DEFAULT 0,       
    m_id bigserial NOT NULL,
    service_id int  DEFAULT NULL,     
    time bigint NOT NULL DEFAULT cast((EXTRACT(EPOCH FROM now() AT TIME ZONE 'UTC') * 1000) as bigint),
    user_id int  DEFAULT NULL,
    end_time DOUBLE PRECISION DEFAULT 0,     
    start_time int NOT NULL DEFAULT 0
);

CREATE INDEX ON ids (time DESC, user_id);
CREATE INDEX ON ids (time DESC, service_id);

SELECT create_hypertable('ids', 'start_time', chunk_time_interval => 604800016);

---------

CREATE TABLE IF NOT EXISTS metrics (
  id bigserial NOT NULL, 
  duration real DEFAULT NULL, 
  metric integer DEFAULT 0,   
  m_id bigint NOT NULL,
  time bigint NOT NULL DEFAULT 0   
);

ALTER TABLE metrics ADD PRIMARY KEY (time, m_id);

CREATE INDEX ON metrics (time DESC);
CREATE INDEX ON metrics (time DESC, measurement );
CREATE INDEX ON metrics (time DESC, m_id );

grant all privileges on ids, metrics to your_db_user;

SELECT create_hypertable('metrics', 'time' , chunk_time_interval => 604800016);

SELECT table_catalog, table_schema, table_name, privilege_type FROM  information_schema.table_privileges WHERE  grantee = 'your_db_user';

---------

DROP TABLE IF EXISTS resource;
CREATE TABLE resource(
id          int NOT NULL,
cpu         text DEFAULT 0,
storing     text DEFAULT 0,
memory      text DEFAULT 0
); 

ALTER TABLE resource ADD PRIMARY KEY (id);

CREATE SEQUENCE resource_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 2147483647
  START 1
  CACHE 1;
ALTER TABLE resource_id_seq
  OWNER TO your_db_user;

ALTER TABLE resource ALTER COLUMN id SET DEFAULT nextval('resource_id_seq'::regclass);

---------

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

DROP TABLE IF EXISTS ns;

CREATE TABLE ns(
id                    bigint NOT NULL,
uuid                  uuid NOT NULL DEFAULT uuid_generate_v4 (),
availability          double precision,
faultTolerance        boolean,
activated             boolean,     
UNIQUE (id, uuid),
PRIMARY KEY(id),
  CONSTRAINT fk_resource
     FOREIGN KEY(id)
         REFERENCES resource(id)
         ON DELETE CASCADE
);

CREATE SEQUENCE ns_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;
ALTER TABLE ns_id_seq
  OWNER TO your_db_user;

ALTER TABLE ns ALTER COLUMN id SET DEFAULT nextval('ns_id_seq'::regclass);

---------

DROP TABLE IF EXISTS authentication;

CREATE TABLE authentication(
id                    integer NOT NULL,
username              character varying(255) NOT NULL,
password              character varying(255) NOT NULL,
host                  character varying(255) NOT NULL,
port                  character varying(10) NOT NULL,    
PRIMARY KEY(id)
);

CREATE SEQUENCE auth_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 2147483647
  START 1
  CACHE 1;
ALTER TABLE auth_id_seq
  OWNER TO your_db_user;

ALTER TABLE authentication ALTER COLUMN id SET DEFAULT nextval('auth_id_seq'::regclass);

---------

DROP TABLE IF EXISTS job;

CREATE TABLE job(
id                    int NOT NULL,
interval              integer NOT NULL,
auth_id               integer REFERENCES authentication (id),
ns_id                 integer REFERENCES ns (id),  
UNIQUE (auth_id, ns_id),
PRIMARY KEY(id)
);

ALTER TABLE job
ADD CONSTRAINT fk_auth_id
FOREIGN KEY (id) REFERENCES authentication (id)
ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED;

ALTER TABLE job
ADD CONSTRAINT fk_ns_id
FOREIGN KEY (id) REFERENCES ns (id)
ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED;

CREATE SEQUENCE job_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 2147483647
  START 1
  CACHE 1;
ALTER TABLE job_id_seq
  OWNER TO your_db_user;

ALTER TABLE job ALTER COLUMN id SET DEFAULT nextval('job_id_seq'::regclass);

---------

DROP TABLE IF EXISTS job_metric;

CREATE TABLE job_metric (
  id                       int NOT NULL,       
  j_id                     int NOT NULL REFERENCES job (id), 
  mj_id                   bigint  NOT NULL,
  jm_time                 bigint NOT NULL 
);
CREATE INDEX ON job_metric (jm_time DESC);
CREATE INDEX ON job_metric (jm_time DESC, id);
CREATE INDEX ON job_metric (jm_time DESC, mj_id);

ALTER TABLE job_metric ADD PRIMARY KEY (jm_time, id);

grant all privileges on job_metric to your_db_user;

SELECT create_hypertable('job_metric', 'jm_time' , chunk_time_interval => 604800016);

CREATE SEQUENCE mjob_metric_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 2147483647
  START 1
  CACHE 1;
ALTER TABLE mjob_metric_id_seq
  OWNER TO your_db_user;

ALTER TABLE job_metric ALTER COLUMN id SET DEFAULT nextval('mjob_metric_id_seq'::regclass);
---------

创建表后,我在使用PostgreSQL 12.6 的数据库中使用了@Laurenz 提出的解决方案,使用 timescaledb 1.7.5 的扩展,如下所示:

#用适当的值填充表格:

UPDATE job_metric AS jm_point
SET jm_time = qm.time
FROM metrics AS qm
WHERE qm.m_id = jm_point.mj_id;

#然后将其设置为NOT NULL:

ALTER TABLE job_metric ALTER jm_time SET NOT NULL;

#定义你的外键:

ALTER TABLE job_metric
   ADD FOREIGN KEY (mj_id, jm_time)
   REFERENCES metrics (time, m_id) MATCH FULL;

#最后一个引用表启用外键的响应: 查询在40毫秒内成功返回。

预期行为: 这个想法是使用表 job_metric 在一个甚至多对多的关系中访问作业和指标表的信息。

实际行为和错误: 创建了表并创建了 FK,但在 job_metric 中插入数据时无法使用,如下所述:

INSERT INTO job_metric (j_id, mj_id, jm_time) 
VALUES(13, 185063, 1621957192266);

错误:不支持超表的外键上下文:SQL 语句“ALTER TABLE _timescaledb_internal._hyper_5_5_chunk ADD CONSTRAINT”5_13_job_metric_j_id_mj_id_jm_time_fkey”外键(j_id,mj_id,jm_time)参考 qmetrics(“时间”,m_id)匹配完整“PL/pgSQL 函数.chunk_constraint_add_table_constraint(_timescaledb_catalog.chunk_constraint) 执行 SQL 状态的第 42 行:0A000

***根据https://docs.timescale.com/timescaledb/latest/overview/limitations/##distributed-hypertable-limitations,看起来上述错误是超表限制的一部分:

不支持引用超表的外键约束。

#Request: 鉴于上述信息和错误,是否有人知道在数据库级别使用 timescaledb 扩展和主要是超表建立关系(多对多或一对多)的任何解决方案?


实际上,当我尝试使用 Django Rest Framework 在表 metrics 和 job_metric 之间创建多对多关系时,我得到了类似的上述错误:

class Job_Metrics(models.Model):
job = models.OneToOneField(Job, on_delete=models.CASCADE)
metrics = models.ManyToManyField(Metrics)
time = models.IntegerField(default=0)

运行应用程序指标直接指出metrics_db: $ python3 manage.py migrate metrics --database=metrics_db

要执行的操作:应用所有迁移:指标运行迁移:应用 metrics.0002_job...Traceback(最近一次调用最后):文件“/var/myproject/myprojectenv/lib/python3.8/site-packages/django/db/ backends/utils.py",第 84 行,在 _execute return self.cursor.execute(sql, params) psycopg2.errors.FeatureNotSupported:不支持超表的外键

如果有人知道解决方案或有想法在 REST API 级别处理上述错误,请您分享您的想法,以访问数据关联表(指标和作业)并在需要删除时一起修改它们,例如,一个job_metric。到目前为止,使用超表修正 timescaledb 扩展似乎不是一个可行的解决方案。

4

0 回答 0