ColdFusion 내에서 .NET AD의 데이터 검색 속도를 높이려면 어떻게 해야 합니까?

StackOverflow https://stackoverflow.com/questions/84795

문제

현재 100,000개 이상의 레코드 풀에서 800개 이상의 레코드를 검색하고 반복하여 레코드당 6개의 필드를 반환하는 데 2분 이상이 소요되는 다음 코드를 어떻게 최적화할 수 있습니까(추가 필드당 약 20초 추가):

<cfset dllPath="C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.DirectoryServices.dll" />
<cfset LDAPPath="LDAP://" & arguments.searchPath />
<cfset theLookUp=CreateObject(".NET","System.DirectoryServices.DirectoryEntry", dllPath).init(LDAPPath) />
<cfset theSearch=CreateObject(".NET","System.DirectoryServices.DirectorySearcher", dllPath).init(theLookUp) />
<cfset theSearch.Set_Filter(arguments.theFilter) />
<cfset theObject = theSearch.FindAll() />

<cfloop index="row" from="#startRow#" to="#endRow#">
   <cfset QueryAddRow(theQuery) />
   <cfloop list="#columnList#" index="col">
     <cfloop from="0" to="#theObject.Get_Item(row).Get_Properties().Get_Item(col).Get_Count()-1#" index="item">
       <cftry>
         <cfset theQuery[col][theQuery.recordCount]=ListAppend(theQuery[col][theQuery.recordCount],theObject.Get_Item(row).Get_Properties().Get_Item(col).Get_Item(item),"|") />
         <cfcatch type="any">
         </cfcatch>
        </cftry>
      </cfloop>
    </cfloop>
  </cfloop>
도움이 되었습니까?

해결책

내부 루프의 항목 목록은 얼마나 됩니까?

어레이로 전환 ~할 것 같다 항목 수가 상당히 많으면 더 빠릅니다.

나는 x0n의 제안과 함께 이것을 구현했습니다 ...

<cfset dllPath="C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.DirectoryServices.dll" />
<cfset LDAPPath="LDAP://" & arguments.searchPath />
<cfset theLookUp=CreateObject(".NET","System.DirectoryServices.DirectoryEntry", dllPath).init(LDAPPath) />
<cfset theSearch=CreateObject(".NET","System.DirectoryServices.DirectorySearcher", dllPath).init(theLookUp) />
<cfset theSearch.Set_Filter(arguments.theFilter) />
<cfset theObject = theSearch.FindAll() />

<cfloop index="row" from="#startRow#" to="#endRow#">

    <cfset Props = theObject.get_item(row).get_properties() />

    <cfset QueryAddRow(theQuery) />

    <cfloop list="#columnList#" index="col">

        <cfset CurrentCol = Props.getItem(col) />

        <cfset ItemArray = ArrayNew(1)/>
        <cfloop from="0" to="#CurrentCol.getcount() - 1#" index="item">
            <cftry>
                <cfset ArrayAppend( ItemArray , CurrentCol.Get_Item(item) )/>
                <cfcatch type="any">
                </cfcatch>
            </cftry>
        </cfloop>
        <cfset theQuery[col][theQuery.recordCount] = ArrayToList( ItemArray , '|' )/>

    </cfloop>

</cfloop>

다른 팁

오랜만에 CF를 접했는데, 의사코드로 힌트를 좀 드릴 수 있겠네요.우선 이 표현은 매우 비효율적입니다.

#theObject.Get_Item(row).Get_Properties().Get_Item(col).Get_Count()-1#

예를 들어 첫 번째 부분인 Get_Item(row)을 선택합니다. 코드를 사용하면 CF가 #columnList# 루프의 각 반복에 대해 행과 해당 속성을 검색하게 됩니다.그리고 무엇보다도 열 목록 반복마다 두 번 수행합니다(루프에 대해 한 번, 내부 cfset에 대해 다시 한 번).생각해 보면 외부 루프의 각 반복(#sfstart#에서 #cfend까지)에 대한 행만 검색하면 됩니다.따라서 의사 코드에서는 다음을 수행합니다.

시작과 끝 사이의 각 행에 대해

cfset props = #theobject.get_item(row).get_properties()#

#columnlist#의 각 열에 대해

cfset currentcol = #props.getitem(col)#

cfset 개수 = #currentcol.getcount() - 1#

0부터 #count#까지 각 항목에 대해

cfset #currentcol.getItem(item)# 등...

말이 되나요?루프에 들어갈 때마다 해당 범위(또는 하위 범위)에서 재사용될 개체를 변수에 캐시합니다.이는 열 루프를 반복할 때마다 열 개체를 한 번만 잡는다는 의미입니다.위에서 수행한 작업에서 볼 수 있듯이 외부 범위에 정의된 모든 변수는 내부 범위에서 사용할 수 있습니다.이전 줄에서 잘라내어 붙여넣고 싶은 마음이 들지만 그렇지 않습니다.결국에는 당신에게만 상처를 입힐 뿐입니다.

도움이 되었기를 바랍니다,

오이신

또한 각 루프에서 cftry 블록을 사용하면 속도가 상당히 느려질 수 있습니다.개별 행이 실패할 것으로 예상되지 않는 한(그리고 해당 지점부터 계속해야 하는 경우) 전체 프로세스에 대해 단일 try/catch 블록을 제안합니다.Try/catch는 비용이 많이 드는 작업입니다.

루프 내에서 너무 많은 평가를 중단하고 대신 변수를 사용하여 개수, col 객체에 대한 포인터 및 쿼리 객체에 커밋할 준비가 될 때까지 파이프 구분 문자열을 유지하고 싶다고 생각합니다. .리팩토링을 올바르게 수행했다면 아래 코드를 사용하면 개선된 점을 알 수 있습니다.

<cfloop index="row" from="#startRow#" to="#endRow#">
<cfset QueryAddRow(theQuery) />
<cfloop list="#columnList#" index="col">
    <cfset PipedVals = "">
    <cfset theItem = theObject.Get_Item(row).Get_Properties().Get_Item(col)>
    <cfset ColCount = theItem.Get_Count()-1>
    <cfloop from="0" to="#ColCount#" index="item">
        <cftry>
        <cfset PipedVals = ListAppend(PipedVals,theItem.Get_Item(item),"|")>
        <cfcatch type="any"></cfcatch>
        </cftry>
    </cfloop>
    <cfset QuerySetCell(theQuery,col) = PipedVals>
</cfloop>

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