Domanda

Ho una vista Django che crea 500-5000 nuovi INSERTI di database in un ciclo. Il problema è che è molto lento! Ricevo circa 100 inserti al minuto su Postgres 8.3. Usavamo MySQL su hardware minore (istanza EC2 più piccola) e non abbiamo mai avuto questo tipo di problemi di velocità.

Dettagli: Postgres 8.3 su Ubuntu Server 9.04. Il server è un "grande" Amazon EC2 con database su EBS (ext3) - 11GB / 20GB.

Ecco alcuni dei miei postgresql.conf: fammi sapere se ne hai bisogno di più

shared_buffers = 4000MB
effective_cache_size = 7128MB

My python:

for k in kw:
        k = k.lower()
        p = ProfileKeyword(profile=self)
        logging.debug(k)
        p.keyword, created = Keyword.objects.get_or_create(keyword=k, defaults={'keyword':k,})
        if not created and ProfileKeyword.objects.filter(profile=self, keyword=p.keyword).count():
            #checking created is just a small optimization to save some database hits on new keywords
            pass #duplicate entry
        else:
            p.save()

Alcuni output dall'alto:

top - 16:56:22 up 21 days, 20:55,  4 users,  load average: 0.99, 1.01, 0.94
Tasks:  68 total,   1 running,  67 sleeping,   0 stopped,   0 zombie
Cpu(s):  5.8%us,  0.2%sy,  0.0%ni, 90.5%id,  0.7%wa,  0.0%hi,  0.0%si,  2.8%st
Mem:  15736360k total, 12527788k used,  3208572k free,   332188k buffers
Swap:        0k total,        0k used,        0k free, 11322048k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                            
14767 postgres  25   0 4164m 117m 114m S   22  0.8   2:52.00 postgres                                                                                                                                            
    1 root      20   0  4024  700  592 S    0  0.0   0:01.09 init                                                                                                                                                
    2 root      RT   0     0    0    0 S    0  0.0   0:11.76 migration/0                                                                                                                                         
    3 root      34  19     0    0    0 S    0  0.0   0:00.00 ksoftirqd/0                                                                                                                                         
    4 root      RT   0     0    0    0 S    0  0.0   0:00.00 watchdog/0                                                                                                                                          
    5 root      10  -5     0    0    0 S    0  0.0   0:00.08 events/0                                                                                                                                            
    6 root      11  -5     0    0    0 S    0  0.0   0:00.00 khelper                                                                                                                                             
    7 root      10  -5     0    0    0 S    0  0.0   0:00.00 kthread                                                                                                                                             
    9 root      10  -5     0    0    0 S    0  0.0   0:00.00 xenwatch                                                                                                                                            
   10 root      10  -5     0    0    0 S    0  0.0   0:00.00 xenbus                                                                                                                                              
   18 root      RT  -5     0    0    0 S    0  0.0   0:11.84 migration/1                                                                                                                                         
   19 root      34  19     0    0    0 S    0  0.0   0:00.01 ksoftirqd/1 

Fammi sapere se altri dettagli sarebbero utili.

È stato utile?

Soluzione

In primo luogo, le operazioni ORM saranno sempre più lente del puro SQL. Una volta ho scritto un aggiornamento a un database di grandi dimensioni nel codice ORM e l'ho impostato in esecuzione, ma l'ho chiuso dopo diverse ore quando aveva completato solo una piccola parte. Dopo averlo riscritto in SQL, il tutto è stato eseguito in meno di un minuto.

In secondo luogo, tieni presente che il tuo codice qui sta eseguendo fino a quattro operazioni di database separate per ogni riga nel tuo set di dati: get in get_or_create, possibilmente anche create , il count sul filtro e infine il save . C'è molto accesso al database.

Tenendo presente che un massimo di 5000 oggetti non è enorme, dovresti essere in grado di leggere l'intero set di dati in memoria all'inizio. Quindi puoi fare un singolo filtro per ottenere tutti gli oggetti Keyword esistenti in una volta sola, salvando un numero enorme di query nel Keyword get_or_create ed evitando anche la necessità di istanziare duplicati ProfileKeywords in primo luogo.

Altri suggerimenti

Un motivo comune per operazioni in blocco lente come questa è che ogni inserzione avviene nella propria transazione. Se riesci a farli accadere tutti in una singola transazione, potrebbe andare molto più veloce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top