Question

J'ai une vue Django qui crée 500 à 5000 nouvelles entrées de base de données dans une boucle. Le problème, c'est que c'est vraiment lent! Je reçois environ 100 insertions par minute sur Postgres 8.3. Nous avions l'habitude d'utiliser MySQL sur du matériel moins important (plus petite instance EC2) et nous n'avions jamais eu ce type de problème de vitesse.

Détails: Postgres 8.3 sur Ubuntu Server 9.04. Le serveur est un "gros" " Amazon EC2 avec base de données sur EBS (ext3) - 11 Go / 20 Go.

Voici certains de mes postgresql.conf - laissez-moi savoir si vous avez besoin de plus

shared_buffers = 4000MB
effective_cache_size = 7128MB

Mon 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()

Une sortie du haut:

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 

Indiquez-moi si d'autres détails vous seraient utiles.

Était-ce utile?

La solution

Tout d’abord, les opérations ORM seront toujours plus lentes que le SQL pur. Une fois, j'ai écrit une mise à jour d'une grande base de données en code ORM et je l'ai configurée pour qu'elle s'exécute, mais je l'ai quittée après plusieurs heures, alors qu'elle n'avait terminé qu'une infime fraction. Après sa réécriture en SQL, le tout a duré moins d’une minute.

Deuxièmement, n'oubliez pas que votre code exécute jusqu'à quatre opérations de base de données distinctes pour chaque ligne de votre ensemble de données - le get dans get_or_create, éventuellement aussi le create , le count sur le filtre, et enfin le save . C'est beaucoup d'accès à la base de données.

Sachant qu’un maximum de 5 000 objets n’est pas énorme, vous devriez pouvoir lire l’ensemble du jeu de données en mémoire au début. Ensuite, vous pouvez créer un seul filtre pour obtenir tous les objets de mot-clé existants en une seule fois, en enregistrant un grand nombre de requêtes dans le mot-clé get_or_create et en évitant également la nécessité d'instancier des doublons. ProfileKeywords en premier lieu.

Autres conseils

Une raison courante pour les opérations d’encombrement lent de ce type est que chaque insertion se produit dans sa propre transaction. Si vous pouvez tous les obtenir en une seule transaction, cela pourrait aller beaucoup plus vite.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top