问题描述
#错误描述: 如果在创建表时定义了外键,则可以创建一个具有到超表中的外键的表
#为了重现,有下一个表格:
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 的数据库中使用了 solution proposed by @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;
预期行为: 这个想法是在多对多关系中使用表 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 约束“5_13_job_metric_j_id_mj_id_jm_time_fkey”外键 (j_id,jm_time) 参考 qmetrics("time",m_id) MATCH FULL " PL/pgsql 函数 _timescaledb_internal.chunk_constraint_add_table_constraint(_timescaledb_catalog.chunk_constraint) EXECUTE sql 状态的第 42 行:0A000
***根据https://docs.timescale.com/timescaledb/latest/overview/limitations/##distributed-hypertable-limitations,看起来上面的错误是hypertable限制的一部分:
不支持引用超表的外键约束。
#Request: 鉴于上述信息和错误,有没有人知道在 DB 级别使用 timescaledb 扩展和主要是 hypertables 建立关系(多对多或一对多)的任何解决方案?
实际上,当我尝试使用 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 中返回 self.cursor.execute(sql,params) psycopg2.errors.FeatureNotSupported:超表的外键是 不支持
如果有人知道解决方案或有想法在 REST API 级别处理上述错误,请分享您的想法,目的是访问数据关联表(指标和作业)并在需要时一起修改它们删除例如job_metric。到目前为止,使用timescaledb扩展的hypertables修改似乎不是一个可行的解决方案。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)