Django Save Object based on PK and another field

送分小仙女□ 提交于 2019-12-11 02:46:37

问题


I am trying to use a partitioned table in postgresql together with a Django installation.

From Googleing the subject, I found out, that Django does not support partitioning by itself, so I did the partitioning of the table myself. I partition my table based on a second field which is a foreign key on another table. The basic model setup is like so:

class Event(models.Model):
    id = models.AutoField(primary_key=True)
    device = models.ForeignKey("Device")
    ... (More Fields)

I have Partitioned the table by the device_id, generating subtables like event_1, event_2 etc. All my querys contain the device id, so the querys are much faster now, but for inserting, django generates an UPDATE Statement like:

UPDATE event SET device=X, ...=X, ... WHERE id=XXX

This results in the database traversing all the partitions of the table to look for the specified ID. Since the device_id never changes, I now want to add the device_id=XXX statement into the WHERE part of the UPDATE statement, which would allow the database to only traverse the one partition.

I think my problem is only a result of the problem, that I don't have the partitioning key in the primary key of my database, but since django only supports one field to be the PK and the partitioning key is not unique, I can't use it as PK.

I can think of two solutions to my problem:

  1. Use a primary key field, that is somehow automatically constructed from an increasing number combined with the device_id (like 1_234). The database would then have to split the primary key to know which device this event is for and which partition it needs to search in.
  2. Change the UPDATE Statement, such that it adds the device_id to the WHERE statement.

The most elegant way in my opinion would be to include the device_id in the primary key. Therefore no changes in Django would be needed and the partitioning would happen only in the database transparent for Django. However I'm not sure if it is possible to create such a primary key in the database.

Thank you for your Help


回答1:


I agree that you would probably be best to leave Django out of it. While I've never done something exactly like this, I think it would be pretty easy to just create a before insert trigger to construct your new, concatenated primary key. Something like this:

CREATE TABLE foo(
  id TEXT NOT NULL,
  device_id INT NOT NULL,
  CONSTRAINT foo_pkey PRIMARY KEY (id)
);

CREATE SEQUENCE foo_id_seq
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;

CREATE OR REPLACE FUNCTION generate_foo_id()
  RETURNS trigger AS
$BODY$
BEGIN
  NEW.id :=  NEW.device_id || '_' || nextval('foo_id_seq');
  RETURN NEW;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

CREATE TRIGGER trigger_generate_foo_id
  BEFORE INSERT
  ON foo
  FOR EACH ROW
  EXECUTE PROCEDURE generate_foo_id();

And you are right, your partition function will have to split it. I've never created a partition function that does this, but I don't know why it would not work. However, you should test and add a comment to this 'answer' with your results (so that future users will benefit from your testing).



来源:https://stackoverflow.com/questions/19706043/django-save-object-based-on-pk-and-another-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!