Ich habe eine Situation, in der Django langsam ist, Zeilen aus einer Tabelle zu löschen, wenn sie über einen Fremdschlüssel (FK) mit einer anderen Tabelle verknüpft sind. aber wurden nicht über das Django ORM erstellt.Django langsam zum Löschen von Zeilen basierend auf Fremdschlüssel, wenn Zeilen nicht durch ORM erstellt werden
Ich habe folgendes Django Modell für Record
:
class Record(models.Model):
job = models.ForeignKey(Job, on_delete=models.CASCADE)
index = models.IntegerField(null=True, default=None)
record_id = models.CharField(max_length=1024, null=True, default=None)
document = models.TextField(null=True, default=None)
error = models.TextField(null=True, default=None)
Das zum Modell zusammenhängt Job
über die job
-Säule (job_id
in MySQL nach Django Migration Erstellung).
Record
Zeilen werden jedoch nicht über Django geschrieben, sondern von Apache Spark über jdbc.write()
. Ein typisches Beispiel könnte 1 Job
mit 45k verwandten Record
Reihen sein.
Das Problem ist, während eine Job
Instanz über die Django ORM über job.delete()
Löschen nicht die zugehörigen Record
Zeilen löschen, ist es ziemlich langsam, 5-7 Sekunden für 1 Job
mit 45k zugeordnet Record
Zeilen 20-30 Sekunden für 160k und so weiter.
Mein Verständnis ist, dass Django emuliertON DELETE CASCADE
, um verschiedene DB-Backends unterzubringen, die Sinn macht. Aber ich frage mich: Wenn die Record
Zeilen nicht über das Django ORM erstellt werden, umgeht das eine Art von interner Django-Indizierung, die sonst dieses kaskadierende Löschen von verknüpften Record
Zeilen viel schneller machen würde?
Die Record
Modell Tabellenerstellung SQL sieht wie folgt aus:
core_record | CREATE TABLE `core_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`index` int(11) DEFAULT NULL,
`record_id` varchar(1024) DEFAULT NULL,
`document` longtext,
`error` longtext,
`job_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `core_record_job_id_8016b123_fk_core_job_id` (`job_id`),
CONSTRAINT `core_record_job_id_8016b123_fk_core_job_id` FOREIGN KEY (`job_id`) REFERENCES `core_job` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=338041 DEFAULT CHARSET=utf8
Wie erwartet, gibt es keine ON DELETE CASCADE
für job_id
ist. Aber ich habe bemerkt, dass die FK-Beschränkung eine seltsame KEY
von core_record_job_id_8016b123_fk_core_job_id
hat, von der ich dachte, dass sie eine Art von interner Django-Indexierung vorschlagen könnte. Nach meinem Verständnis indexiert eine InnoDB-Engine automatisch FK-Beziehungen, aber diese Affordanz wird nicht genutzt, wenn Django die Tabellen über das ORM verwaltet.
Ein Ansatz scheint, wie es könnte sein, die core_record
Tabelle zu ändern ON DELETE CASCADE
für den FK aufzunehmen, und dann Django anweisen nichts on_delete
zu tun, auf MySQL angewiesen geordneten Zeilen zu löschen. Aber ich frage mich, ob es Alternativen gibt? Ich möchte vermeiden, die Tabelle manuell zu ändern, wenn möglich, und Django erlauben, die SQL-Migrationen zu verwalten.
Wenn Django eine Art von interner Indexierung für FKs hat, gibt es eine Möglichkeit, Datenbank-/Tabellenzeilen in Django zu indizieren, wenn das ORM die Zeilen nicht erstellt hat?
Alle Vorschläge oder Einsichten sehr geschätzt.