Sto costruendo un sito Web Django con un backend Oracle e osservo prestazioni molto lente anche quando eseguo semplici ricerche sulla chiave primaria. Lo stesso codice funziona molto velocemente quando gli stessi dati vengono caricati in MySQL.Scarsa performance di Django ORM con Oracle
Quale potrebbe essere il motivo della scarsa prestazione? Ho il sospetto che il problema sia legato all'uso dei parametri di collegamento Oracle, ma potrebbe non essere il caso.
Django modello (una tabella di test con ~ 6.200.000 righe)
from django.db import models
class Mytable(models.Model):
upi = models.CharField(primary_key=True, max_length=13)
class Meta:
db_table = 'mytable'
Django ORM (prende ~ 1s)
from myapp.models import *
r = Mytable.objects.get(upi='xxxxxxxxxxxxx')
interrogazione grezza con i parametri bind (prende ~ 1s)
cursor.execute("SELECT * FROM mytable WHERE upi = %s", ['xxxxxxxxxxxxx'])
row = cursor.fetchone()
print row
interrogazione crudo senza legano parametri (istantanea)
cursor.execute("SELECT * FROM mytable WHERE upi = 'xxxxxxxxxxxxx'")
row = cursor.fetchone()
print row
Il mio ambiente
- Python 2.6.6
- Django 1.5.4
- cx-Oracle 5.1.2
- Oracle 11g
Quando si collega al database Oracle a specificare:
'OPTIONS': {
'threaded': True,
}
Ogni aiuto sarà molto apprezzato.
[Update] Ho fatto qualche ulteriore prova utilizzando lo strumento debugsqlshell
dalla barra degli strumenti di debug Django.
# takes ~1s
>>>Mytable.objects.get(upi='xxxxxxxxxxxxx')
SELECT "Mytable"."UPI"
FROM "Mytable"
WHERE "Mytable"."UPI" = :arg0 [2.70ms]
Questo suggerisce che Django utilizza i parametri legano Oracle e query stessa è molto veloce, ma la creazione dell'oggetto Python corrispondente richiede un tempo molto lungo.
Giusto per confermare, ho eseguito la stessa query utilizzando cx_Oracle (si noti che il cursor
nella mia domanda originale è il Django cursor).
import cx_Oracle
db= cx_Oracle.connect('connection_string')
cursor = db.cursor()
# instantaneous
cursor.execute('SELECT * from mytable where upi = :upi', {'upi':'xxxxxxxxxxxxx'})
cursor.fetchall()
Cosa potrebbe rallentare Django ORM?
[Aggiornamento 2] Abbiamo esaminato le prestazioni del database dal lato Oracle e si scopre che l'indice non viene utilizzato quando la query proviene da Django. Qualche idea sul perché questo potrebbe essere il caso?
Hai controllato l'indice per il campo di ricerca esistono in db? – esauro
Quando controllo la tabella in SQL Developer, vedo che esiste un indice normale valido su quella colonna. – apetrov
Cosa succede se si eseguono le 2 versioni in SQL Developer e i piani di query sono diversi (utilizzare i pulsanti Spiega piano o Tracciamento automatico)? Per le variabili di bind usa 'SELECT * FROM mytable WHERE upi =: s' e SQL Developer ti chiederà il valore. –