Frage

Ich habe eine ziemlich einfache Abfrage (dieses Mal), die ich die Ergebnisse von ALL muß zurück (ich sie in einer Excel-Tabelle bin zu speichern). Die Abfrage selbst mal aus dem Server, so wie gehe ich davon, ohne dass das passiert ausgeführt wird?

War es hilfreich?

Lösung

Der einfachste Weg wäre, die Domäne der Abfrage in mehrere Teile zu brechen. So fügen Sie einen Ausdruck in der WHERE-Klausel, die nur die erste Hälfte des Schlüsselbereiches auswählt, dann eine zweite Abfrage ausführen, um die untere Hälfte zu wählen. Dann die Ausgabe zusammenführen.

Andere Tipps

Sie können die Zeitüberschreitung der Anforderung für die Seite erhöhen:

<cfsetting requestTimeout="3600" />

Dies wird sicherstellen, dass Sie Zeit haben, um alle Einträge zu verarbeiten.

Sie können auch die Liste brechen in „Brocken“. Es wird einige Tuning benötigen, um herauszufinden, was die optimale Blockgröße ist, aber man konnte die Ergebnisse 100 oder 1000 Zeilen zu einer Zeit, und verwenden Sie greift die Ergebnisse aus, um den Bildschirm zu drücken, sobald sie verfügbar werden. Dieser Ansatz hat auch den Vorteil der Verwendung von weniger Speicher auf dem Coldfusion-Server, da jede Zeile wieder aus dem SQL gezogen Server in CFML den Speicher geladen wird, und setzt sich dort, bis die Abfrage Objektvariable überschrieben ist oder sich außerhalb des Geltungsbereichs (am Ende Die Seite). Dies bedeutet, dass Sie leicht Speicher Coldfusion füllen können mehrere hunderttausend Zeilen lesen, vor allem, wenn die Zeilen „breit“ (das heißt großen Varchars oder Texte enthalten).

off zuerst würde ich überprüfen, um zu sehen, warum diese Abfrage so lange dauert.

Was können Sie auf Datenbankebene tun, um die Leistung der Abfrage zu verbessern. klingt vielleicht nicht haben Sie die Datenbank korrekt indiziert. nehmen Sie die Abfrage und wirft es in ein Programm, das Sie den Ausführungsplan analysieren. suchen die Lags und Adresse, um sie.

mehr Leistung zu erhalten, schauen Sie in indizierte Ansichten erstellen, wenn Ihre Datenbank so etwas unterstützt.

nächster Blick auf einige Teile der Abfrage aus Caching. gibt es keinen Grund für jede Anforderung tut Berechnungen auf historische Daten werden, wenn sie einmal durchgeführt werden können und dann in einer Tabelle irgendwo im Cache gespeichert.

wie für die Coldfusion Ende. stellen Sie sicher, dass Sie java.io.BufferedWriter verwenden die Tabelle zu erstellen. ein normalen Zeichenfolge Verkettungsverfahren unter Verwendung von CF ist Hund langsam und BufferedWriter ist unendlich schneller. Beigefügt ist ein CFC ich für die Erstellung von tabed begrenzten Tabellen erstellt hat, können Sie es ändern, um Ihre Bedürfnisse anzupassen.

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

Wie andere haben darauf hingewiesen, Sie könnten versuchen, die Anforderung Timeout der Seite zu erhöhen, obwohl dies nicht ratsam ist, die Ausführung, wenn Ihre Abfrage gemessen wird Minuten , anstatt Sekunden oder Millisekunden. CF wird zu einem Zeitpunkt nur eine bestimmte Anzahl von Anfragen bedienen, so dass Sie wollen über das Blockieren eines dieser Anfragen vorsichtig sein, warten auf einer 5-minütigen Abfrage abzuschließen.

Wenn Sie SQL Server oder Oracle verwenden, glaube ich CFQUERY macht sein eigenes pro-Abfrage-Timeout-Attribut, das Sie einstellen können. Auch dies für wirklich nicht ratsam, lange Abfragen ausgeführt werden.

In meiner Erfahrung, wenn Ihre Abfrage entweder so komplex ist, oder so viele Daten zurückgibt, die es braucht, Minuten zu laufen, dann ist es Zeit, um die Ausführung der Abfrage von der Anforderung, der Eingeweihten zu entkoppeln es. Es gibt eine Reihe von Möglichkeiten, wie Sie dies tun könnten, wie zum Beispiel:

  1. Erstellen Sie eine Art System von Warteschlangen anstehenden Serviceanforderungen zu erfassen. Dies könnte eine DB-Tabelle, eine XML-Datei auf der Festplatte sein usw. Wenn Ihre Benutzer fordern ihre Daten, die Sie diesen Antrag mit dieser Warteschlange registrieren.

  2. Schreiben Sie eine geplante Aufgabe (zum Beispiel Java, DTS, oder eine geplante CF Seite), die über diese Warteschlange für Arbeit überprüft. Je nach Bedarf könnten Sie einen Hintergrund-Thread ausgliedern zu behandeln jede Anfrage, oder vielleicht die geplante Aufgabe übernimmt es direkt. Wenn Sie mit geplanten CF-Seiten, Sie wollen die gesamte Arbeitsbelastung zerbrechen in kleinere Stücke, die iterativ behandelt werden können, sonst werden Sie das gleiche Problem haben Sie jetzt haben.

  3. Wenn die geplante Aufgabe feststellt, dass eine Anforderung gefüllt wurde, tritt es irgendeine Art von Meldung aus, die Verarbeitung bereit ist. Zum Beispiel könnten Sie den Benutzer per E-Mail ihnen sagen, die Daten bereit ist, mit einem Link eine CSV-Datei herunterzuladen, die auf der Festplatte erstellt wurden.

Offensichtlich hängt die richtige Wahl viel auf das spezifische Problem nicht gelöst. Im Allgemeinen würde ich diese Dinge versuchen, in dieser Reihenfolge:

  1. Aggressiv die Abfrageausführungszeit angreifen. Können Sie Indizes oder besser schreiben T-SQL verwenden?
  2. Wenn die Abfrage dauert eine Minute oder zwei, und ist sehr selten laufen, Seite oder Abfrage-Timeouts zu erhöhen könnte akzeptabel sein.
  3. Wenn die Abfrage oft ausgeführt wird, oder dauert länger als 2-3 Minuten, den sauren Apfel beißen und bauen System eine Dosier- oder Schlange, um die Abfrage im Hintergrund zu behandeln.

Sie können die Zeit festgelegt auf einer Basis pro Anforderung obwohl mehrere Abfragen Verschmelzung kann ein besserer Ansatz sein.

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

Verwenden Sie die Indizierung richtig. Erstellen Sie Fremdschlüssel, wo immer Sie können. Abfragen werden nie für eine db Zeitüberschreitung, die normalisiert wird.

Seien Sie sehr vorsichtig mit Verknüpfungen und Klauseln, wie wenn Sie Klausel in der Abfrage dort anstelle der Verwendung group by Klausel where haben, wird having Klausel schneller arbeiten. So Abfrageausführungszeit reduziert wird.

Verwenden Sie die Kostenschätzung zu prüfen, welche Tabelle die meiste Zeit nimmt oder muss Normalisierung in Ihrem db.

Ich würde die Abfrage in einen separaten Thread werfen, es in einen persistenten Umfang Laden (zB Sitzung). Vorwärts zu einer Seite, die für die Existenz der Abfrage überprüft. Wiederholen Sie die Prüfung, bis die Abfrage vorhanden ist, dann weiter zu einer Seite, die zeigt / Prozesse / Was immer es.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top