문제

루프에 500-5000 개의 새 데이터베이스 인서트를 생성하는 Django보기가 있습니다. 문제는 정말 느리다는 것입니다! Postgres 8.3에서 분당 약 100 개의 삽입물을 받고 있습니다. 우리는 Lesser Hardware (더 작은 EC2 인스턴스)에서 MySQL을 사용했으며 이러한 유형의 속도 문제가 없었습니다.

세부 사항 : 우분투 서버 9.04의 Postgres 8.3. 서버는 EBS (EXT3) -111GB/20GB의 데이터베이스가있는 "대형"Amazon EC2입니다.

다음은 내 Postgresql.conf 중 일부입니다. 더 필요한지 알려주세요.

shared_buffers = 4000MB
effective_cache_size = 7128MB

내 파이썬 :

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

상단에서 일부 출력 :

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 

다른 세부 사항이 도움이 될지 알려주세요.

도움이 되었습니까?

해결책

첫째, ORM 작업은 항상 순수한 SQL보다 느리게 진행됩니다. 한 번 ORM 코드의 대형 데이터베이스에 대한 업데이트를 작성하여 실행 중이었지만 작은 분수 만 완료 한 후 몇 시간 후에 종료했습니다. SQL로 다시 작성한 후 모든 것이 1 분 안에 실행되었습니다.

둘째, 여기에서 귀하의 코드는 데이터 세트의 모든 행에 대해 최대 4 개의 개별 데이터베이스 작업을 수행하고 있음을 명심하십시오. get get_or_create에서 아마도 create,, count 필터와 마지막으로 save. 그것은 많은 데이터베이스 액세스입니다.

최대 5000 개 객체가 크지 않다는 점을 염두에두고 시작시 전체 데이터 세트를 메모리로 읽을 수 있어야합니다. 그런 다음 싱글을 할 수 있습니다 filter 기존의 모든 키워드 개체를 한 번에 가져 오려면 키워드에 수많은 쿼리를 저장합니다. get_or_create 또한 처음에 중복 프로파일 키워드를 인스턴스화 할 필요가 없습니다.

다른 팁

이와 같은 느린 벌크 작업의 일반적인 이유 중 하나는 자체 트랜잭션에서 발생하기 때문입니다. 단일 트랜잭션에서 모든 것이 발생할 수 있다면 훨씬 빠르게 진행될 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top