2013-09-24 2 views
11

오라클 백엔드가있는 Django 웹 사이트를 구축 중이며 기본 키를 간단히 조회하더라도 성능이 매우 저하됩니다. 같은 코드가 MySQL에서 동일한 데이터가로드 될 때 매우 빠르게 작동합니다.오라클과 Django ORM의 성능이 좋지 않습니다.

성능 저하의 원인은 무엇일까요? 이 문제는 Oracle 바인드 매개 변수 사용과 관련이 있다는 의심이 들지만, 그렇지 않을 수도 있습니다.

장고 모델 (~ 6,200,000 행이 테스트 테이블)

from django.db import models 

class Mytable(models.Model): 
    upi = models.CharField(primary_key=True, max_length=13) 

    class Meta: 
     db_table = 'mytable' 

장고 ORM이 (소요 ~ 1 초)

from myapp.models import * 
r = Mytable.objects.get(upi='xxxxxxxxxxxxx') 
바인드 매개 변수을 가진 원시 쿼리 (소요

~ 1s)

cursor.execute("SELECT * FROM mytable WHERE upi = %s", ['xxxxxxxxxxxxx']) 
row = cursor.fetchone() 
print row 
어떤 바인드와

원시 쿼리는 5.1.2

cursor.execute("SELECT * FROM mytable WHERE upi = 'xxxxxxxxxxxxx'") 
row = cursor.fetchone() 
print row 

내 환경 (순간)

  • 파이썬 2.6.6
  • 장고 1.5.4
  • CX-오라클 매개 변수
  • 오라클 11g
  • Oracle 데이터베이스에 연결하는 경우

내가 지정

'OPTIONS': { 
    'threaded': True, 
} 

어떤 도움을 크게 감상 할 수 있습니다.

[업데이트] 난 장고 디버그 도구 모음에서 debugsqlshell 도구를 사용하여 몇 가지 추가 테스트를했다.

# takes ~1s 
>>>Mytable.objects.get(upi='xxxxxxxxxxxxx') 
SELECT "Mytable"."UPI" 
FROM "Mytable" 
WHERE "Mytable"."UPI" = :arg0 [2.70ms] 

이 장고 오라클 바인드 매개 변수를 사용하고 쿼리 자체가 매우 빠르지 만 해당 파이썬 객체를 생성하는 것은 매우 시간이 오래 걸리는 것이 좋습니다.

확인하려면 cx_Oracle을 사용하여 동일한 쿼리를 실행했습니다. 원래 질문에서 cursorDjango 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() 

장고 ORM 속도를 저하시킬 수있는 것은 무엇입니까?

[업데이트 2] 우리는 오라클 측에서 데이터베이스 성능을 바라 보았다, 그것은 쿼리가 장고에서 오는 경우 인덱스를 사용하지 않는 것으로 나타났다. 왜 이것이 사실 일지 모르는 어떤 아이디어?

+0

당신이 조회 필드에 대한 인덱스를 확인 했이 DB에 존재 여기

나를 도와 몇 가지 유용한 토론 스레드입니까? – esauro

+0

SQL Developer에서 테이블을 검사 할 때 해당 열에 유효한 일반 인덱스가 있음을 알 수 있습니다. – apetrov

+0

SQL Developer에서 2 가지 버전을 실행하고 쿼리 계획이 다른 경우 (Explain Plan 또는 Autotrace 단추 사용) 어떻게됩니까? 바인드 변수의 경우 SELECT * FROM mytable WHERE upi = : s'을 사용하면 SQL Developer에서 값을 묻는 메시지를 표시합니다. –

답변

1

DBA와 함께 작업 한 후 어떤 이유로 Django get(upi='xxxxxxxxxxxx') 쿼리가 데이터베이스 인덱스를 사용하지 않는 것으로 나타났습니다.

filter(upi='xxxxxxxxxxxx')[:1].get()을 사용하여 동일한 쿼리를 다시 작성하면 쿼리가 빠릅니다.

get 쿼리는 정수 기본 키 (원래 질문의 문자열)를 사용하는 경우에만 빠릅니다.

최종 솔루션은

create index index_name on Mytable(SYS_OP_C2C(upi)); 

cx_Oracle과 오라클이 사용하는 문자 집합 사이에 불일치가있는 것으로 보인다. C2C 색인을 추가하면 문제가 해결됩니다.

업데이트 : 또한 Oracle의 VARCHAR2에서 NVARCHAR2로 전환해도 기능 색인과 같은 효과가 있으며 사용할 수 있습니다. http://comments.gmane.org/gmane.comp.python.db.cx-oracle/3049 http://comments.gmane.org/gmane.comp.python.db.cx-oracle/2940

2

성능 문제 해결해야 TO_CHAR(character) 사용 :

cursor.execute("SELECT * FROM mytable WHERE upi = TO_CHAR(%s)", ['xxxxxxxxxxxxx']) 
관련 문제