كيفية تشغيل كبيرة جدا الاستعلام (SQL Server و كولد فيوجن)

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

  •  03-07-2019
  •  | 
  •  

سؤال

لدي معقول استعلام بسيط (هذه المرة) التي أنا في حاجة إلى كل من (أنا تخزينها في جدول بيانات Excel).الاستعلام نفسه مرات الخادم ، لذا كيف يمكنني تشغيله دون أن يحدث ؟

هل كانت مفيدة؟

المحلول

وأسهل طريقة ستكون لكسر مجال الاستعلام إلى عدة أجزاء. على سبيل المثال، إضافة إلى جملة WHERE تعبير يختار فقط في النصف الأول من النطاق الرئيسي، ثم قم بتشغيل استعلام 2ND لتحديد النصف السفلي. ثم دمج الإخراج.

نصائح أخرى

ويمكنك زيادة طلب مهلة للصفحة:

<cfsetting requestTimeout="3600" />

وهذا سوف نتأكد من أن لديك الوقت لمعالجة كافة الإدخالات.

وأنت قد تحتاج أيضا إلى كسر قائمة تصل إلى "قطع". وسوف تتطلب بعض ضبط لمعرفة ما هو حجم قطعة الأمثل، ولكن هل يمكن أن الاستيلاء على نتيجة 100 أو 1000 خطوط في وقت واحد، واستخدام لدفع النتائج إلى الشاشة عندما تصبح متاحة. ويتميز هذا النهج أيضا الاستفادة من استخدام ذاكرة أقل على خادم كولد فيوجن، وسحب كل الصف الخلفي من SQL يحصل على تحميل الخادم في الذاكرة CFML، ويجلس هناك حتى متغير الكائن الاستعلام الكتابة أو يخرج من نطاق (في نهاية الصفحة). هذا يعني أنه يمكنك بسهولة ملء الذاكرة كولد فيوجن قراءة مئات الآلاف من الصفوف، وخاصة إذا كانت الصفوف "واسعة" (أي التي تحتوي على varchars كبيرة أو النصوص).

وأول قبالة أود أن تحقق لمعرفة لماذا هذا الاستعلام يأخذ وقتا طويلا.

وماذا يمكنك أن تفعل في مستوى قاعدة البيانات لتحسين أداء الاستعلام. يبدو وكأنه ربما لم يكن لديك قاعدة البيانات المفهرسة بشكل صحيح. تأخذ الاستعلام ورميها في بعض البرامج التي يمكن تحليل خطة التنفيذ. بحث عن التخلف ومعالجتها.

للحصول على مزيد من الأداء، والنظر في خلق وجهات النظر فهرستها إذا كانت قاعدة البيانات تدعم هذا النوع من الشيء.

ونظرة المقبل في التخزين المؤقت بعض أجزاء من الاستعلام بها. ليس هناك من سبب ليتم إجراء الحسابات على البيانات التاريخية لكل طلب عندما يمكن أن يتم ذلك مرة واحدة ثم مؤقتا في جدول في مكان ما.

وكما في نهاية كولد فيوجن. تأكد من أنك تستخدم java.io.BufferedWriter لإنشاء جداول البيانات. باستخدام طريقة سلسلة سلسلة العادي في CF هو الكلب بطيئة وBufferedWriter هو مطلق وأسرع. المرفقة هي CFC أنا خلقت لخلق tabed محدد جداول البيانات، يمكنك تعديله ليناسب احتياجاتك.

<!--- init --->
<cffunction name="init" access="public" returntype="Any" output="false">
    <cfargument name="name" type="string" required="true">
    <cfset var local = {}>

    <!--- name of file when downloading --->
    <cfset variables.name = arguments.name & ".xls">
    <!--- name of temp file --->
    <cfset variables.filename = CreateUUID() & ".csv">
    <!--- full path to temp file for downloading --->
    <cfset variables.fullfilename = expandpath("/_temp") & "\" & variables.filename>
    <!--- file write java object --->
    <cfset variables.filewriter = CreateObject("java","java.io.FileWriter").init(
            variables.fullfilename
            ,JavaCast("boolean","true")
        )>
    <!--- buffered writer java object --->
    <cfset variables.bufferedwriter = CreateObject("java","java.io.BufferedWriter").init(
                variables.filewriter
            )>
    <!--- row delimeter --->
    <cfset variables.row = chr(10)>
    <!--- col delimeter --->
    <cfset variables.col = chr(9)>
    <!--- header container --->
    <cfset variables.headers = []>
    <!--- data container --->
    <cfset variables.data = []>
    <cfset newrow()>
    <cfreturn this>
</cffunction>


<!--- addheader --->
<cffunction name="addheader" access="public" returntype="void" output="false">
    <cfargument name="str" type="string" required="true">
    <cfset arrayappend(variables.headers, arguments.str)>
</cffunction>

<!--- newrow --->
<cffunction name="newrow" access="public" returntype="void" output="false">
    <cfset arrayappend(variables.data, arraynew(1))>
    <cfset variables.data_counter = arraylen(variables.data)>
</cffunction>

<!--- adddata --->
<cffunction name="adddata" access="public" returntype="void" output="false">
    <cfargument name="str" type="string" required="true">
    <cfset arrayappend(variables.data[variables.data_counter], arguments.str)>
</cffunction>

<!--- flush --->
<cffunction name="flush" access="public" returntype="void" output="false">
    <cfset var local = {}>

    <!--- write headers --->
    <cfset local.counter = 0>
    <cfset local.headers_count = arraylen(variables.headers)>
    <cfloop array="#variables.headers#" index="local.header">
        <cfset local.counter++>
        <cfset variables.bufferedwriter.write(local.header & variables.col)>
    </cfloop>

    <cfif not arrayisempty(variables.headers)>
        <cfset variables.bufferedwriter.write(variables.row)>
    </cfif>

    <!--- write data --->
    <cfloop array="#variables.data#" index="local.data">
        <cfloop array="#local.data#" index="local.cell">
            <cfset variables.bufferedwriter.write(local.cell & variables.col)>
        </cfloop>
        <cfset variables.bufferedwriter.write(variables.row)>
    </cfloop>

    <cfset variables.bufferedwriter.close()>
    <cfsetting showdebugoutput="No">
    <cfheader name="Content-Description" value="File Transfer">
    <cfheader name="Content-Disposition" value="attachment;filename=#variables.name#">
    <cfcontent type="application/vnd.ms-excel" file="#variables.fullfilename#" deletefile="true" reset="true">
</cffunction>

كما أشار آخرون ، قد تتمكن من محاولة زيادة طلب مهلة من الصفحة ، على الرغم من أن هذا ليس من المستحسن إذا كان الاستعلام التنفيذ يتم قياسها في دقائق, بدلا من ثانية أو أجزاء من الثانية.CF فقط خدمة عدد محدد من الطلبات في وقت واحد ، إذا كنت تريد أن تكون حذرا حول حبس واحد من تلك الطلبات في انتظار على بعد 5 دقائق سيرا على الاستعلام لإكمال.

إذا كنت تستخدم SQL Server أو Oracle, أعتقد CFQUERY يعرض الخاصة في مهلة الاستعلام السمة التي يمكنك تعيينها.مرة أخرى هذا ليس من المستحسن حقا طويلة تشغيل الاستعلامات.

في تجربتي, إذا كان الاستعلام الخاص بك إما معقدة أو إرجاع الكثير من البيانات التي يلزم دقائق لتشغيل, ثم حان الوقت لفصل تنفيذ الاستعلام من طلب أن يبدأ.هناك عدد من الطرق التي يمكن أن تفعل هذا ، مثل:

  1. خلق نوعا من الاصطفاف نظام لتسجيل انتظار طلبات الخدمة.هذا يمكن أن يكون DB الجدول, XML ملف على القرص, الخ.عندما يطلب المستخدم البيانات الخاصة بهم تسجيل هذا الطلب مع هذا الانتظار.

  2. كتابة المهام المجدولة (مثلا ، جافا, DTS, أو المقرر انظر الصفحة) في أن يتحقق دوريا هذا الانتظار للحصول على عمل.اعتمادا على الاحتياجات الخاصة بك قد العرضية مؤشر ترابط خلفية التعامل مع كل طلب ، أو ربما المهمة المجدولة مقابض مباشرة.إذا كنت تستخدم المقرر راجع الصفحات, سوف تحتاج إلى كسر إجمالي عبء العمل إلى مجموعات أصغر يمكن التعامل معها تكرارا, وإلا سيكون لديك نفس المشكلة لديك الآن.

  3. مرة المهمة المجدولة يحدد أن الطلب قد تم شغلها ، فإنه ينطلق من نوع إشعار بأن المعالجة جاهزة.فعلى سبيل المثال ، قد البريد الإلكتروني للمستخدم أن أقول لهم البيانات جاهزة ، مع رابط تحميل .ملف csv الذي تم إنشاؤه على القرص.

ومن الواضح أن الحق في الاختيار يعتمد كثيرا على المشكلة المحددة التي يجري حلها.عموما سأحاول هذه الأمور في هذا النظام:

  1. بقوة الهجوم وقت تنفيذ الاستعلام.يمكنك استخدام الفهارس أو كتابة أفضل T-SQL ؟
  2. إذا كان الاستعلام يستغرق دقيقة أو دقيقتين ، يتم تشغيل نادرا جدا ، وزيادة الصفحة أو الاستعلام مهلة قد تكون مقبولة.
  3. إذا كان يتم تشغيل الاستعلام في كثير من الأحيان ، أو يأخذ أكثر من 2-3 دقائق ، لدغة الرصاصة وبناء الخلط أو الطابور نظام التعامل مع الاستعلام في الخلفية.

ويمكنك ضبط الوقت على أساس لكل طلب على الرغم من أن دمج استعلامات متعددة قد يكون نهجا أفضل.

<cfsetting 
enableCFoutputOnly = "yes|no" 
requestTimeOut = "value in seconds"
showDebugOutput = "yes|no" >

واستخدام الفهرسة بشكل صحيح. إنشاء المفاتيح الخارجية أي وقت مضى حيث يمكنك. سوف الاستفسارات تنقضي أبدا لديسيبل وهو تطبيع.

كن حذرا جدا مع الصلات وشروط، مثل إذا كان لديك group by بند في الاستعلام الخاص بك هناك بدلا من استخدام بند where، سوف بند having العمل بشكل أسرع. وبالتالي تقليل وقت تنفيذ الاستعلام.

وتقدير تكلفة استخدام للتحقق من أي جدول يأخذ معظم الوقت أو يحتاج التطبيع في ديسيبل الخاص بك.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top