2012-01-26 3 views
0

예 :한계/오프셋 선택으로 select_related를 최적화하는 방법은 무엇입니까?

# consider the following query run in a loop 
q = Users.objects.all().select_related('profile', 'address')[start:start+batchsize] 

# assume start == 1,000,000 and batchsize == 1000 
print q.query 

SELECT ... LEFT OUTER JOIN profile ... LIMIT 1000 OFFSET 1000000; 

문제 :

여기 select_related 그렇지 않으면, 장고는 것 때문에 내 쿼리 속도를 사용하여 별도의 DB는 나중에 그들에 액세스 할 때 프로필/주소 (및 다른 많은 테이블)을 얻기 위해 호출 루프. 그러나 OFFSET이 클 때 반복의 시작 속도가 빨라지지만 실제로는 느려집니다.

1) 다른이 문제가 발생 했습니까? 2) 장고에이 문제를 해결할 수있는 임시 해결책이 있습니까?

나는 이것이 MySQL 쿼리 엔진에 문제가 있다고 의심하지만 단지 MySQL에서 쿼리 최적화 프로그램을 돕기 위해 내 장고 코드를 구조화 할 수 있는지 알고 싶습니다.

감사합니다.

+0

실제로 물체를 "q"로 수화해야합니까? 아니면 정말로 특정 가치가 필요합니까? 객체 대신 values_list를 반환하여 반환되는 것과 같습니다. – Brandon

답변

1

"해결 방법"에는 아무 것도 없습니다. 이는 예상되는 동작입니다. select_related 당신이 먹는 각 외래 키에 대해 SQL JOIN을 수행합니다. 이것은 본질적으로 처리 할 데이터베이스에 대한보다 복잡한 쿼리입니다. 테이블의 행이 많을수록 길어집니다.

실제로이 시나리오에서 수행 할 수있는 작업은 최대한 많은 최적화를 테이블에 적용하는 것입니다. profile_idaddress_id 열이 아직 색인화되어 있지 않으면 색인을 추가해야합니다 (단, Django에서 이미 수행 한 것으로 의심됨).

모든 입력란이 필요하지 않은 경우 .values() 또는 .values_list()를 사용하여 (처리 적은 그물 작업을 필요로하는) ​​더 제한 쿼리. 당신도 거기에 profileaddress에 필드를 지정할 수 있습니다. 그러나

, 해당 필드는 이미 색인, 당신은 모든 데이터를해야하는 경우 중 하나 느린 것을 다루거나 데이터베이스에 대해 좀 더 과감한 조치를 취해야합니다. 서버가 아닌 경우 자체 서버에 저장하여 서버에 더 많은 리소스 (RAM, 코어 등)를 제공 할 수 있습니다. 힘이 부족한 경우 부하 등을 분배하는 클러스터를 만듭니다.

관련 문제