2011-05-05 5 views
2

많은 조인을 사용하여 마스터 쿼리를 수행하는 응용 프로그램을 작성하고 있습니다. 그런 다음이 쿼리 데이터를 전체 응용 프로그램에서 전역 변수로 재생할 수 있습니다. 쿼리를 새로 고치거나 각 페이지를 새로 고칠 때 최신 결과 집합을 가져옵니다. 그래서 그것은 요청의 수명 동안 같은 상태에 있습니다.QoQ 또는 다른 방법을 빠르게 할 수 있습니까?

이 응용 프로그램의 다른 부분에서는 종종이 데이터에서 100 분의 100 분량의 QoQ를 실행합니다. 일반적으로 재귀 함수 호출의 결과입니다. 그러나 QoQ는 훌륭한 기능이지만 너무 빠르지 않고 때로는 페이지로드가 나쁜 날에 3000 - 5000ms 사이가 될 수 있습니다. 그것은 단지 충분히 빠르지 않다.

QoQ를 더 빠르게 수행 할 수있는 최적화 기술이 있습니까? 아니면 다른 방법으로 수행 할 수 있습니까? Ben Nadel의 Duplicate() 함수에 대한 흥미로운 기사를 읽었습니다. 사용하는 범위가 있습니까? 그렇다면 어떻게 사용합니까?

나는 당신의 생각을 듣고 싶습니다.

미친 제안에 대해 걱정하지 마십시오. 개인 프로젝트이므로 위험을 감수하고 있습니다. 저는 CF8과 호환되는 Railo에서 이것을 실행하고 있습니다.

많은 감사, 마이클.

+0

글로벌 쿼리는 각 페이지 뷰에서 업데이트됩니까? 이전 요청이 실행되는 동안 데이터가 업데이트되는 상황에서 충돌이 발생하지 않을까요? – Yisroel

+0

이 글로벌 쿼리에 대한 모든 QoQ는 단순히보기 위해 데이터를 검색하도록 선택됩니다. 이 쿼리는 업데이트되지 않습니다. QoQ는 단지 최신 결과 집합을 검색하고 보여주기 때문에 DB 레코드에 대한 업데이트가 있어도 어쨌든 중요하지 않습니다. –

답변

2

QoQ의 코드와 복잡성을 보지 않고도 최선의 방법을 말하기는 어렵지만 한 가지 방법은 구조체를 사용하여 QoQ 외부의 레코드를 인덱싱하는 것입니다. QoQ를 사용하는 오버 헤드의 대부분은 새로운 쿼리 개체를 작성하는 것입니다. 예를 들어 원본 쿼리를 반복하고 비교하는 것보다 구조체 쓰기 전용 방법을 사용하는 것이 훨씬 효율적입니다. 예를 들어

:

<!--- build up index ---> 
<cfset structindex = {} /> 
<cfset fields = "first,last,company" /> 
<cfloop list="#fields#" index="field"> 
    <cfset key = "field:#field#,value:#q[field][currentrow]#" /> 
    <!--- initialize each key (instead of using stuctkeyexists) ---> 
    <cfloop query="q"> 
     <cfset structindex[key] = "" /> 
    </cfloop> 
    <cfloop query="q"> 
     <!--- update each key with list of matching row indexes ---> 
     <cfset structindex[key] = listappend(structindex[key], currentrow) /> 
    </cfloop> 
</cfloop> 

<!--- save structindex to global variable ---> 

<!--- output rows matching index ---> 
<cfset key = "field:company,value:stackexchange" /> 
<cfoutput> 
    <cfloop list="#structindex[key]#" index="row"> 
     #q.last[row]#, #q.first[row]# (#q.company[row]#)<br /> 
    </cfloop> 
</cfoutput> 

이 당신의 필요가 일부 전분기 문장의 예와 얼마나 많은 레코드를 제공 일치하지 않는 경우는 메인 쿼리에 있습니다.

1

먼저 마스터 쿼리가 수행 한 시간을 살펴 보겠습니다. 그것은 시간의 일부 마운트에 대한 캐시 수 있으며 pageload 시간의 좋은 덩어리를 복용하는 경우, 나는 그것을 캐쉬 것이다.

다음으로, 재귀 호출을 살펴 보겠습니다. 그것들을 반복적으로 만들 수 있다면, 아마도 속도가 빨라질 것입니다. 항상 이것이 가능하지는 않다는 것을 알고 있습니다. 이것이 당신의 가장 큰 시간을 낭비하지 않는다면 나는 놀랄 것입니다. 당신이하고있는 일에 대해 더 많이 알지 못해도 이것을 최적화하는 것을 돕기는 어렵습니다.

DB 서버에 재귀 QoQ의 저장 프로 시저를 작성하는 것도 고려해 볼 수 있습니다.이 저장 프로 시저는 데이터를 신속하게 처리하고 효율적으로 슬라이스하고 다이스하도록 설계되었습니다. CF는 아닙니다. QoQ는 매우 유용하지만 속도 악마는 아닙니다 (언급 한대로).

마지막으로 직선 필터를 찾고 QoQ를 사용하지 않을 것입니다. 오히려 표준 cfoutput 태그에서 마스터 쿼리에 대한 루프를 실행하고 즉시 필터링합니다. 즉, 마스터 쿼리가 한 번, 결과 쿼리가 한 번이 아니라 마스터 쿼리를 한 번 반복합니다.

+0

마스터 쿼리가 빠르므로 문제가되지 않습니다. 당신은 맞습니다 - 재귀 호출이 가장 오래 걸립니다. 나는 기본적으로 즉석에서 동적으로 검색하고 데이터를 얻기 위해 필요한 몇 가지 하위/부모 관계가 있습니다. 예를 들어, 10 개의 항목이 있고 루프 된 경우 각 항목은 상위 수준에 도달 할 때까지 상위 항목과의 관계를 구축하기 위해 추가 QoQ 기능을 호출 할 수 있습니다. CMS에서 동적 인 Sitemap 구조와 조금 비슷하다고 상상해보십시오. 더 나은 접근 방법이 있습니까? 나무를 얻기 위해 함수를 작성할 수는 있지만, 즉각적인 호출이 필요합니다. –

+0

나는 몇 가지 시도 할 생각할 수 있습니다. 주먹은 한 번에 모든 레벨을 푸는 것을 피할 수 있다면, 클릭 할 수있는 트리 (또는 디스플레이 구조가 무엇이든)를 만들고 AJAX 호출을 만들어 주문형 레벨을 얻을 수 있습니다. 당신은 또한 DB가 QoQ가 현재하고있는 작업을 할 수있게 해줄 수 있습니다. 또한 각 노드를 스택에 밀어 넣고 한 번에 하나씩 꺼내서 반복적으로 작성할 수도 있지만 처음 두 제안보다 코딩하는 데 더 많은 시간이 필요합니다. –

1

두 가지 기본 솔루션이 있습니다. 먼저 QoQ 외부의 레코드로 CF에서 뭔가를 할 수 있습니다. 나는 이것에 대한 나의 제안을 이미 올렸다. 다른 하나는 DB에서 모든 것을 처리하는 것입니다. 한 가지 방법은 임시 테이블로 하위 쿼리를 사용하는 것입니다. SQL 문을 전역 변수에 보관 한 다음 현재 QoQ가있는 동일한 위치에서 참조하지만 데이터베이스에 대한 실제 쿼리를 수행 할 수도 있습니다. 그것은 하나의 여행 DB 및 다음에 많은 QoQ보다 느리게 들릴지 모르지만 실제로는 효율적으로 인덱싱되지 않을 것입니다.

select * 
from (
    #sqlstring# 
) as tmp 
where company = 'stackexchange' 

사실에 접근하고 또한 그들이 그 기록에 대한 필터링 할 수 있어야한다 사용자를 기록하는 것을 모두 복잡한 기준을 시스템에 이런 짓을했는지. 이 접근법을 사용하면 매 쿼리가 올바르게 실행되도록하는 대신 내부 레코드의 원본을 항상 알 수 있습니다.

편집 : 가능한 경우 queryparams를 사용하는 것이 실제로 더 안전하고 일반적으로 더 효율적입니다. SQL 문의 파일을 포함하여이 작업을 수행 할 수있는 것으로 나타났습니다 ...

select * 
from (
    <cfinclude template="master_subquery.cfm" /> 
) as tmp 
where company = 'stackexchange' 
관련 문제