2008-09-17 12 views
2

Как я могу оптимизировать следующий код, который в настоящее время занимает более 2 минут для получения и записи более 800 записей из пула более 100 тыс. Записей, возвращая 6 полей на запись (добавляет приблизительно 20 секунд на дополнительное поле):Как ускорить извлечение данных из .NET AD в ColdFusion?

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

ответ

2

Насколько велик список элементов для внутреннего цикла?

Переключение на массив может быть Быстрее, если есть значительное количество предметов.

Я реализовал это вместе с предложениями 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> 
2

Прошло много времени с тех пор, как я коснулся CF, но я могу дать некоторые намеки на псевдокод. С одной стороны, это выражение очень inefficent:

# theObject.Get_Item (ряд) .Get_Properties() Get_Item (цв) .Get_Count() - 1 #

Возьмите первую часть, например, Get_Item (. строка) - ваш код заставляет CF возвращать строку и ее свойства для каждой итерации цикла # columnList #; и, прежде всего, вы делаете это TWICE за итерацию списка столбцов (один раз для цикла и снова для внутреннего cfset). Если вы думаете об этом, ему нужно только получить строку для каждой итерации внешнего цикла (от # sfstart # до #cfend). Так, в псевдокоде это сделать:

для каждой строки между началом и концом

CFSET реквизит = # theobject.get_item (ряд) .get_properties() #

для каждой седловины в # # columnlist

CFSET currentcol = # props.getitem (Col) #

счетчик CFSET = #current col.getcount() - 1 #

Еогеасп вещь от 0 до # подсчитывать #

CFSET # currentcol.getItem (пункт) # и т.д. ...

Имеют смысл? Каждый раз, когда вы вводите цикл, кешируют объекты, которые будут повторно использоваться в этой области (или дочерних областях) в переменной. Это означает, что вы только захватываете объект столбца один раз за итерацию цикла столбца. Все переменные, определенные во внешних областях, доступны во внутренних областях, как вы можете видеть в том, что я сделал выше. Я знаю его соблазн вырезать и вставлять из предыдущих строк, но не надо. Это только причиняет вам боль в конце.

надеюсь, что это помогает,

Oisin

+0

переменного счетчик/кэширование не надо - CF будет кэшировать от/до значений cfloop , (хотя и не для оператора цикла в cfscript) – 2008-09-17 18:01:55

+0

я бы так подумал, но я пытался продемонстрировать точку. – x0n 2008-09-17 19:17:04

1

Кроме того, с использованием блока cftry в каждом цикле, вероятно, замедляя это вниз совсем немного. Если вы не ожидаете, что отдельные строки потерпят неудачу (и вам нужно продолжить с этой точки), я бы предложил один блок try/catch для всего процесса. Try/catch - это дорогостоящая операция.

+0

Да, но в этом случае я ожидаю плохие или отсутствующие данные ... так, что я должен жить. Вопрос: Учитывая другие предложения, я предполагаю, что могу обойти это, снова проверив itemCount в самом нижнем поле – Brian 2008-09-17 18:24:42

+0

, я не могу говорить о CF, но на любом другом языке с try/catch и исключениями это не попытка/catch это дорого, это создание исключения. Это связано с тем, что исключение содержит трассировку стека - то есть список всех методов, которые вызывались до этой точки. – x0n 2008-09-17 19:15:00

0

Я думаю, что вы хотели бы, чтобы прекратить делать так много оценок внутри ваших петель и вместо того, чтобы использовать переменные для хранения отсчетов, указатели на объект Col и задержите трубопрокатный DELIM строки до тех пор, пока вы готов к фиксации объекта запроса. Если я сделал рефакторинг правильно, вы должны заметить улучшение, если вы используете код ниже:

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