2009-12-10 23 views
36

Ich möchte Daten von der Datenbank (MySQL) von JPA erhalten, ich will es nach einem Spaltenwert sortiert.Datenbank Sortierung vs Programmatic Java Sortierung

Also, was ist die beste Praxis zu:

  • die Daten abrufen aus der Datenbank als Liste von Objekten (JPA), dann Art es einige Java-APIs programmatisch verwenden.

ODER

  • die Datenbank sortieren Lassen Sie durch eine Sortierauswahlabfrage verwenden.

Vielen Dank im Voraus

+2

Manchmal ist es nicht eine einfache Technologie-Wahl, in meinem Fall ist die db sehr beschäftigt und wird wahrscheinlich zum Engpass, so dass ich HAVA im Speicher sortieren. – shellbye

Antwort

46

Wenn Sie eine Teilmenge aller Datenbankdaten abrufen, z. B. 20 Zeilen auf dem Bildschirm von 1000 anzeigen, ist es besser, nach der Datenbank zu sortieren. Dies wird schneller und einfacher und Sie können eine Seite der Zeilen (20, 50, 100) auf einmal abrufen, anstatt alle.

Wenn Ihr Dataset relativ klein ist, ist die Sortierung in Ihrem Code möglicherweise bequemer, wenn Sie eine komplexe Sortierung implementieren möchten. Normalerweise kann diese komplexe Sortierung in SQL durchgeführt werden, aber nicht so einfach wie im Code.

Kurz gesagt, ist die Faustregel Sortierung über SQL, mit einigen Rand Fällen zur Regel.

+1

+1 für die Nuance. asdf –

+3

Ich muss der "Faustregel" widersprechen. Das Sortieren in der Datenebene ist teuer, da der typische Anwendungsfall darin besteht, dass mehrere Sortierreihenfolgen für dieselbe Ergebnismenge erforderlich sind, wobei das Sortieren in der Anwendungsebene, dh das Ändern der Anzeigereihenfolge der Daten in der Präsentationsebene, viel sinnvoller ist vom Standpunkt der Bequemlichkeit und Skalierbarkeit. –

+1

Was passiert, wenn ich gegen API/Dienste gehe, um meine Daten zu bekommen? und vor allem beinhaltet es mehr als eine API-Aufrufe. – Matt

1

die Datenbank Lassen Sie die Sortierung tun. Es ist gebaut, um die "schmutzige" Arbeit für Sie zu erledigen ...

4

Ich bin fast sicher, dass es schneller sein wird, damit die Datenbank es sortieren kann. Es gibt Ingenieure, die viel Zeit damit verbringen, ihre Suchalgorithmen zu perfektionieren und zu optimieren, während Sie einen eigenen Sortieralgorithmus implementieren müssen, der einige weitere Berechnungen hinzufügen kann.

3

Ich würde die Datenbank die Sortierung machen lassen, sie sind im Allgemeinen sehr gut darin.

28

Im Allgemeinen ist es besser, ORDER BY in Ihrer SQL-Abfrage zu verwenden - auf diese Weise erhalten Sie, wenn es einen gültigen Index gibt, Ihre Sortierung "kostenlos" (im schlimmsten Fall wird es die gleiche Menge sein) von Arbeit, wie es in deinem Code tut, aber oft ist es weniger Arbeit als das!).

+0

Der typische Anwendungsfall ist, dass eine einzelne Ergebnismenge mehrere Sortierreihenfolgeanforderungen hat, so dass der Nutzen eines Index begrenzt ist, sofern Sie nicht jede Sortieranforderung jeder Abfrage mit einem Index abdecken ... was für die meisten Systeme nicht realistisch ist . Sortieren in der Anwendungsebene, d. H. In der Lage ist, die Anzeigereihenfolge einer gegebenen Ergebnismenge auf irgendeine Weise zu ändern, auf die der Benutzer entscheidet, dass sie sortiert werden soll, ohne eine weitere Anforderung an die Datenebene zu stellen, macht aus Bequemlichkeits- und Skalierbarkeitsgesichtspunkten viel mehr Sinn. –

+0

@ opc.three Erstens, ich stimme nicht zu, es ist ein typischer Anwendungsfall, es hängt von Ihrer App ab. Zweitens, was ist, wenn Sie eine Teilmenge von Big Data abrufen wollen? Würden Sie all diese Millionen von Datensätzen aus einer Datenquelle holen und mit ihnen im Speicher umgehen? Und zuletzt hätte ich keine Angst davor, Anfragen an eine Datenebene zu senden, weil Sie es ohnehin oft machen müssen (zB wenn ein Benutzer andere Suchkriterien eingibt) und weil Sie Caching oder spezielle Systeme (zB solr) immer verwenden können Wenn Sie die Suche/Abfrage und db allein beschleunigen möchten, ist nicht genug. –

+0

>> Zweitens, was ist, wenn Sie eine Teilmenge von Big Data abrufen werden? Würden Sie all diese Millionen von Datensätzen aus einer Datenquelle holen und mit ihnen im Speicher umgehen? << Das ist nicht der Anwendungsfall in Frage. In Ihrem Beispiel benötigen Sie ORDER BY, um das richtige Ergebnis zu erhalten. In dem Beispiel im Originalkommentar kommt das ORDER BY einfach zum Vorteil der Präsentationsschicht ... Äpfel und Orangen. Sie können es ablehnen, aber es ist ein typischer Anwendungsfall. Beim Caching und Sortieren in einer Anwendungsebene haben Sie beim Skalieren mehr Möglichkeiten. –

16

Dies ist nicht vollständig auf den Punkt, aber ich habe vor kurzem etwas, das sich auf die Datenbank vs Anwendung Sortierung bezieht geschrieben. Der Artikel ist über eine .net-Technik, so dass die meisten es wahrscheinlich nicht für Sie interessant sein, aber die Grundprinzipien bleiben:

auf der Client-Seite Sortierung Aufschieben (zB jQuery, Dataset/Dataview Sortierung) kann aussehen verlockend. Und es ist tatsächlich ein gangbarer Weg für Paging, Sortieren und Filtern, wenn (und nur dann):

1. die Menge der Daten klein ist, und

1. gibt es wenig Besorgnis über Leistung und Skalierbarkeit

Aus meiner Erfahrung gibt es nur wenige Systeme, die diese Kriterien erfüllen.Beachten Sie, dass das Sortieren/Paging in der Anwendung/Datenbank nicht gemischt und zugeordnet werden kann. Wenn Sie die Datenbank nach unsortierten 100 Datenzeilen fragen und diese Zeilen dann auf der Anwendungsseite sortieren, werden Sie das Set wahrscheinlich nicht erhalten von Daten, die Sie erwartet haben. Das mag offensichtlich erscheinen, aber ich habe den Fehler oft genug gesehen, dass ich es zumindest erwähnen wollte.

Es ist viel effizienter, aus einer Reihe von Gründen in der Datenbank zu sortieren und zu filtern. Zum einen sind Datenbank-Engines stark darauf optimiert, genau die Art von Arbeit zu erledigen, die das Sortieren und Filtern beinhaltet; Dafür wurde der zugrunde liegende Code entwickelt. Aber selbst wenn man davon ausgeht, dass man Code schreiben könnte, der der Sortier-, Filter- und Paging-Leistung einer ausgereiften Datenbank-Engine entspricht, ist es trotzdem vorzuziehen, diese Arbeit in der Datenbank auszuführen, weil sie effizienter zu begrenzen ist die Menge an Daten, die von der Datenbank an den Anwendungsserver übertragen werden. Wenn Sie beispielsweise 10.000 Zeilen vor dem Filtern haben und Ihre Abfrage diese Zahl auf 75 reduziert, führt die Filterung auf dem Client dazu, dass die Daten aus allen 10.000 Zeilen über die Leitung (und in Ihre App) übertragen werden Serverspeicher), wobei die Filterung auf der Datenbankseite dazu führen würde, dass nur die gefilterten 75 Zeilen zwischen Datenbank und Anwendung verschoben würden. Dies kann enorme Auswirkungen auf die Leistung und Skalierbarkeit haben.

Der vollständige Beitrag ist hier: http://psandler.wordpress.com/2009/11/20/dynamic-search-objects-part-5sorting/

1

die Datenbank sortieren Lassen. Dann können Sie mit JPA leicht paginieren, ohne das gesamte Ergebnis zu lesen.

11

Ich stieß auf genau diese Frage und entschied, dass ich ein kleines Benchmark ausführen sollte, um die Geschwindigkeitsunterschiede zu quantifizieren. Die Ergebnisse haben mich überrascht. Ich möchte meine Erfahrung mit dieser Art von Frage posten.

Wie bei einigen der anderen Poster hier mein Gedanke war, dass die Datenbank-Ebene würde die Sortierung schneller tun, weil sie angeblich für diese Art von Dingen eingestellt sind. @Alex hat darauf hingewiesen, dass die Datenbank schneller ist, wenn die Datenbank bereits einen Index für die Sortierung enthält. Ich wollte die Frage beantworten, welche rohe Sortierung bei nicht indizierten Sortierungen schneller ist. Beachte, ich sagte schneller, nicht einfacher. Ich denke, in vielen Fällen ist die Arbeit einfacher und weniger fehleranfällig.

Meine Hauptannahme war, dass die Sortierung in den Hauptspeicher passen würde. Nicht alle Probleme werden hier passen, aber eine gute Anzahl. Für nicht genügend Speicher kann es gut sein, dass Datenbanken hier leuchten, obwohl ich das nicht getestet habe. Im Fall von In-Memory-Sortierungen übertraf alles von Java/C/C++ Mysql in meinem informellen Benchmark, wenn man es so nennen könnte.

Ich wünschte, ich hätte mehr Zeit gehabt, um die Datenbank-Ebene im Vergleich zur Anwendungsschicht, aber leider andere Aufgaben genannt gründlich zu vergleichen. Trotzdem konnte ich nicht anders, als diese Notiz für andere aufzuzeichnen, die diese Straße entlangfahren.

Als ich diesen Weg begann, sah ich mehr Hürden. Soll ich die Datenübertragung vergleichen? Wie? Kann ich die Zeit vergleichen, um db vs Zeit zu lesen, um eine flache Datei in Java zu lesen? Wie kann man die Sortierzeit gegenüber der Datentransferzeit gegenüber der Zeit isolieren, um die Datensätze zu lesen? Mit diesen Fragen hier war die Methodik und Timing-Nummern, die ich gefunden habe.

Alle Zeiten in ms, sofern nicht anders

geschrieben

Alle Sortierroutinen waren die von der Sprache zur Verfügung gestellt Standardwerte (diese sind gut genug für gelegentliche sortierte Daten)

Alle Kompilation war mit einem typischen „Release-Profil“ via netbeans ohne Anpassung gewählt, es sei denn

Alle Tests für mysql sonst

geschrieben verwendet das folgende Schema

mysql> CREATE TABLE test_1000000 
(
pk bigint(11) NOT NULL, 
float_value DOUBLE NULL, 
bigint_value  bigint(11) NULL, 
PRIMARY KEY (pk) 
) Engine MyISAM; 

mysql> describe test_1000000; 
+--------------+------------+------+-----+---------+-------+ 
| Field  | Type  | Null | Key | Default | Extra | 
+--------------+------------+------+-----+---------+-------+ 
| pk   | bigint(11) | NO | PRI | NULL |  | 
| float_value | double  | YES |  | NULL |  | 
| bigint_value | bigint(11) | YES |  | NULL |  | 
+--------------+------------+------+-----+---------+-------+ 

Hier ist ein kleiner Ausschnitt, um die DB zu füllen. Es kann einfacher Weise sein, aber das ist, was ich tat:

public static void BuildTable(Connection conn, String tableName, long iterations) { 
    Random ran = new Random(); 
    Math.random(); 
    try { 


     long epoch = System.currentTimeMillis(); 
     for (long i = 0; i < iterations; i++) { 
      if (i % 100000 == 0) { 
       System.out.println(i + " next 100k"); 
      } 
      PerformQuery(conn, tableName, i, ran.nextDouble(), ran.nextLong()); 
     } 

    } catch (Exception e) { 
     logger.error("Caught General Exception Error from main " + e); 

    } 
} 

MYSQL Direkt CLI Ergebnisse:

select * from test_10000000 order by bigint_value limit 10; 
10 rows in set (2.32 sec) 

Diese Zeiten waren etwas schwierig, da die einzige Info, das ich die Zeit nach der Hinrichtung berichtet hatte, war des Befehls.

von mysql-Eingabeaufforderung für 10000000 Elemente es etwa 2.1 bis 2.4 ist entweder für bigint_value Sortieren oder float_value

Java JDBC MySQL-Aufruf (eine ähnliche Leistung zu Art, die aus mysql cli tun)

public static void SortDatabaseViaMysql(Connection conn, String tableName) { 

    try { 
     Statement stmt = conn.createStatement(); 
     String cmd = "SELECT * FROM " + tableName + " order by float_value limit 100"; 


     ResultSet rs = stmt.executeQuery(cmd); 
    } catch (Exception e) { 

    } 

} 

Fünf Läufe:

Java Sort Zufallszahlen beim Fliegen generieren (war eigentlich langsamer als das Lesen der Datenträger-IO).Einsatzzeit ist die Zeit, Zufallszahlen zu erzeugen, und füllen Sie das Array

Aufruf wie

JavaSort(10,10000000); 

Timing-Ergebnisse:

assignment time 331 sort time 1139 
assignment time 324 sort time 1037 
assignment time 317 sort time 1028 
assignment time 319 sort time 1026 
assignment time 317 sort time 1018 
assignment time 325 sort time 1025 
assignment time 317 sort time 1024 
assignment time 318 sort time 1054 
assignment time 317 sort time 1024 
assignment time 317 sort time 1017 

Diese Ergebnisse zum Lesen einer Datei von Doppel im Binär-Modus waren

assignment time 4661 sort time 1056 
assignment time 4631 sort time 1024 
assignment time 4733 sort time 1004 
assignment time 4725 sort time 980 
assignment time 4635 sort time 980 
assignment time 4725 sort time 980 
assignment time 4667 sort time 978 
assignment time 4668 sort time 980 
assignment time 4757 sort time 982 
assignment time 4765 sort time 987 

Eine Pufferübertragung führt zu viel schnelleren Laufzeiten

assignment time 77 sort time 1192 
assignment time 59 sort time 1125 
assignment time 55 sort time 999 
assignment time 55 sort time 1000 
assignment time 56 sort time 999 
assignment time 54 sort time 1010 
assignment time 55 sort time 999 
assignment time 56 sort time 1000 
assignment time 55 sort time 1002 
assignment time 56 sort time 1002 

C und C++ Timing-Ergebnisse (unten Quelle sehen)

Debug Profil mit qsort

assignment 0 seconds 110 milliseconds Time taken 2 seconds 340 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 2 seconds 340 milliseconds 
assignment 0 seconds 100 milliseconds Time taken 2 seconds 330 milliseconds 
assignment 0 seconds 100 milliseconds Time taken 2 seconds 340 milliseconds 
assignment 0 seconds 100 milliseconds Time taken 2 seconds 330 milliseconds 
assignment 0 seconds 100 milliseconds Time taken 2 seconds 340 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 2 seconds 340 milliseconds 
assignment 0 seconds 100 milliseconds Time taken 2 seconds 330 milliseconds 
assignment 0 seconds 100 milliseconds Time taken 2 seconds 340 milliseconds 
assignment 0 seconds 100 milliseconds Time taken 2 seconds 330 milliseconds 

Freisetzungsprofil mit qsort

assignment 0 seconds 100 milliseconds Time taken 1 seconds 600 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 1 seconds 600 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 1 seconds 580 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 1 seconds 590 milliseconds 
assignment 0 seconds 80 milliseconds Time taken 1 seconds 590 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 1 seconds 590 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 1 seconds 600 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 1 seconds 590 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 1 seconds 600 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 1 seconds 580 milliseconds 

Freisetzungsprofil std :: Sortieren (a, a + ARRAY_SIZE);

assignment 0 seconds 100 milliseconds Time taken 0 seconds 880 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 0 seconds 870 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 0 seconds 890 milliseconds 
assignment 0 seconds 120 milliseconds Time taken 0 seconds 890 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 0 seconds 890 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 0 seconds 880 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 0 seconds 900 milliseconds 
assignment 0 seconds 90 milliseconds Time taken 0 seconds 890 milliseconds 
assignment 0 seconds 100 milliseconds Time taken 0 seconds 890 milliseconds 
assignment 0 seconds 150 milliseconds Time taken 0 seconds 870 milliseconds 

Freisetzungsprofil Zufallsdaten aus der Datei lesen und mit std :: sort (a, a + ARRAY_SIZE)

assignment 0 seconds 50 milliseconds Time taken 0 seconds 880 milliseconds 
assignment 0 seconds 40 milliseconds Time taken 0 seconds 880 milliseconds 
assignment 0 seconds 50 milliseconds Time taken 0 seconds 880 milliseconds 
assignment 0 seconds 50 milliseconds Time taken 0 seconds 880 milliseconds 
assignment 0 seconds 40 milliseconds Time taken 0 seconds 880 milliseconds 

Im Folgenden ist der Quellcode verwendet. Hoffentlich minimale Bugs :)

Java-Quelle Beachten Sie, dass innerhalb von JavaSort die runCode und writeFlag angepasst werden müssen, je nachdem, was Sie möchten. Beachten Sie auch, dass die Speicherzuweisung geschieht in der for-Schleife (also Testen GC, aber ich habe keinen nennenswerten Unterschied sehen die Zuweisung außerhalb der Schleife zu bewegen)

public static void JavaSort(int iterations, int numberElements) { 

    Random ran = new Random(); 
    Math.random(); 
    int runCode = 2; 
    boolean writeFlag = false; 
    for (int j = 0; j < iterations; j++) { 
     double[] a1 = new double[numberElements]; 
     long timea = System.currentTimeMillis(); 
     if (runCode == 0) { 
      for (int i = 0; i < numberElements; i++) { 
       a1[i] = ran.nextDouble(); 

      } 
     }    
     else if (runCode == 1) { 

      //do disk io!! 
      try { 
      DataInputStream in = new DataInputStream(new FileInputStream("MyBinaryFile.txt")); 
      int i = 0; 
      //while (in.available() > 0) { 
      while (i < numberElements) { //this should be changed so that I always read in the size of array elements 
       a1[i++] = in.readDouble(); 
      } 
      } 
      catch (Exception e) { 

      } 

     } 
     else if (runCode == 2) { 
      try { 
       FileInputStream stream = new FileInputStream("MyBinaryFile.txt"); 
       FileChannel inChannel = stream.getChannel(); 

       ByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); 
       //int[] result = new int[500000]; 

       buffer.order(ByteOrder.BIG_ENDIAN); 
       DoubleBuffer doubleBuffer = buffer.asDoubleBuffer(); 
       doubleBuffer.get(a1); 
      } 
      catch (Exception e) { 

      } 
     } 

     if (writeFlag) { 
      try { 
       DataOutputStream out = new DataOutputStream(new FileOutputStream("MyBinaryFile.txt")); 
       for (int i = 0; i < numberElements; i++) { 
        out.writeDouble(a1[i]); 
       } 
      } catch (Exception e) { 

      } 
     } 
     long timeb = System.currentTimeMillis(); 
     Arrays.sort(a1); 

     long timec = System.currentTimeMillis(); 
     System.out.println("assignment time " + (timeb - timea) + " " + " sort time " + (timec - timeb)); 
     //delete a1; 
    } 
} 

C/C++ Quelle

#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <fstream> 

#include <cstdlib> 
#include <ctime> 
#include <cstdio> 
#include <math.h> 
#include <stdio.h> 
#include <time.h> 
#include <stdlib.h> 

#define ARRAY_SIZE 10000000 

using namespace std; 

int compa(const void * elem1, const void * elem2) { 
    double f = *((double*) elem1); 
    double s = *((double*) elem2); 
    if (f > s) return 1; 
    if (f < s) return -1; 
    return 0; 
} 

int compb (const void *a, const void *b) { 
    if (*(double **)a < *(double **)b) return -1; 
    if (*(double **)a > *(double **)b) return 1; 
    return 0; 
} 

void timing_testa(int iterations) { 

    clock_t start = clock(), diffa, diffb; 

    int msec; 
    bool writeFlag = false; 
    int runCode = 1; 

    for (int loopCounter = 0; loopCounter < iterations; loopCounter++) { 
     double *a = (double *) malloc(sizeof (double)*ARRAY_SIZE); 
     start = clock(); 
     size_t bytes = sizeof (double)*ARRAY_SIZE; 
     if (runCode == 0) { 
      for (int i = 0; i < ARRAY_SIZE; i++) { 
       a[i] = rand()/(RAND_MAX + 1.0); 
      } 
     } 
     else if (runCode == 1) { 
      ifstream inlezen; 

      inlezen.open("test", ios::in | ios::binary); 


      inlezen.read(reinterpret_cast<char*> (&a[0]), bytes); 

     } 
     if (writeFlag) { 
      ofstream outf; 
      const char* pointer = reinterpret_cast<const char*>(&a[0]); 
      outf.open("test", ios::out | ios::binary); 
      outf.write(pointer, bytes); 
      outf.close(); 

     } 

     diffa = clock() - start; 
     msec = diffa * 1000/CLOCKS_PER_SEC; 
     printf("assignment %d seconds %d milliseconds\t", msec/1000, msec % 1000); 
     start = clock(); 
     //qsort(a, ARRAY_SIZE, sizeof (double), compa); 
     std::sort(a, a + ARRAY_SIZE); 
     //printf("%f %f %f\n",a[0],a[1000],a[ARRAY_SIZE-1]); 
     diffb = clock() - start; 

     msec = diffb * 1000/CLOCKS_PER_SEC; 
     printf("Time taken %d seconds %d milliseconds\n", msec/1000, msec % 1000); 
     free(a); 
    } 



} 

/* 
* 
*/ 
int main(int argc, char** argv) { 

    printf("hello world\n"); 
    double *a = (double *) malloc(sizeof (double)*ARRAY_SIZE); 


    //srand(1);//change seed to fix it 
    srand(time(NULL)); 

    timing_testa(5); 



    free(a); 
    return 0; 
} 
1

Well , es gibt nicht wirklich einen einfachen Weg, dies zu beantworten; es muss im Zusammenhang beantwortet werden.

Wird Ihre Anwendung (Middle Tier) im selben Knoten wie die Datenbank ausgeführt?

Wenn ja, müssen Sie sich keine Gedanken über die Wartezeit zwischen der Datenbank und der mittleren Ebene machen. Dann stellt sich die Frage: Wie groß ist die Teilmenge/Ergebnismenge Ihrer Anfrage? Denken Sie daran, dass zum Sortieren der mittleren Ebene eine Liste/ein Satz der Größe N verwendet wird, und schreiben Sie entweder einen benutzerdefinierten Vergleich oder verwenden Sie den Standard-Vergleichskomparator. Oder Wasauchimmer. Am Anfang sind Sie also durch die Größe N zurückgestuft.

Aber wenn die Antwort nein ist, dann werden Sie von der Latenz bei der Übertragung Ihrer Ergebnismenge von der DB in die mittlere Schicht getroffen. Und wenn Sie Seitenumbrüche durchführen, was das letzte ist, was Sie tun sollten, werfen Sie 90-95% dieser Ergebnismenge weg, nachdem Sie die Seiten geschnitten haben.

So kann die verschwendete Bandbreite nicht gerechtfertigt werden. Stellen Sie sich vor, Sie tun dies für jede Anfrage in Ihren Mieterorganisationen.

Wie auch immer Sie es betrachten, das ist schlechtes Design.

Ich würde dies in der Datenbank tun, egal was. Nur weil heutzutage fast alle Anwendungen Paginierung verlangen; Selbst wenn sie keine massiven Resultsets über das Kabel zu Ihrem Kunden schicken, ist das eine totale Verschwendung; zieht alle über all Ihre Mieter hin.

Eine interessante Idee, die ich mit diesen Tagen spiele, ist die Nutzung der HTML5, 2-Wege-Datenbindung in Browser-Frameworks wie Angular, und einige Verarbeitung zurück zum Browser schieben. Auf diese Weise enden Sie nicht in der Leitung für jemand anderen vor Ihnen, um zu beenden. Echte verteilte Verarbeitung. Aber man muss sorgfältig entscheiden, was man schieben kann und was nicht.