كيف يمكنني تسريع عملية استرجاع البيانات من .NET AD ضمن ColdFusion؟

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

سؤال

كيف يمكنني تحسين التعليمة البرمجية التالية، والتي تستغرق حاليًا أكثر من دقيقتين لاسترداد أكثر من 800 سجل من مجموعة تضم أكثر من 100 ألف سجل، وإرجاع 6 حقول لكل سجل (يضيف حوالي 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 = #theobject.get_item(row).get_properties()#

لكل عمود في #columnlist#

cfset currentcol = #props.getitem(col)#

عدد cfset = #currentcol.getcount() - 1#

foreach عنصر من 0 إلى #count#

cfset #currentcol.getItem(item)# الخ...

منطقي؟في كل مرة تدخل فيها حلقة، يتم تخزين الكائنات مؤقتًا التي سيتم إعادة استخدامها في هذا النطاق (أو النطاقات الفرعية) في متغير.هذا يعني أنك تقوم بالتقاط كائن العمود مرة واحدة فقط لكل تكرار لحلقة العمود.جميع المتغيرات المحددة في النطاقات الخارجية متوفرة في النطاقات الداخلية، كما ترون في ما قمت به أعلاه.أعلم أنه من المغري القص واللصق من الأسطر السابقة، لكن لا تفعل ذلك.لن يؤذيك إلا في النهاية.

أتمنى أن يساعدك هذا،

أويسين

بالإضافة إلى ذلك، من المحتمل أن يؤدي استخدام كتلة cftry في كل حلقة إلى إبطاء هذا الأمر قليلاً.ما لم تكن تتوقع فشل صفوف فردية (وتحتاج إلى المتابعة من تلك النقطة)، أود أن أقترح كتلة محاولة/التقاط واحدة للعملية بأكملها.تعتبر عملية المحاولة/الالتقاط عملية مكلفة.

أعتقد أنك تريد التوقف عن إجراء العديد من التقييمات داخل حلقاتك وبدلاً من ذلك استخدام المتغيرات للاحتفاظ بالأعداد والمؤشرات إلى كائن 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