Techniken zum Abfragen eines Objekt-In-Memory-Satzes in einer Java-Anwendung

8

Wir haben ein System, das eine 'grobe Suche' durchführt, indem es eine Schnittstelle auf einem anderen System aufruft, die eine Menge von Java-Objekten zurückgibt. Sobald wir die Suchergebnisse erhalten haben, muss ich in der Lage sein, die resultierenden Java-Objekte basierend auf bestimmten Kriterien, die den Zustand der Attribute beschreiben, weiter zu filtern (z. B. von den anfänglichen Objekten gebe alle Objekte zurück, wobei xy & gt; z & amp; & amp; ab == c).

Die Kriterien, die verwendet werden, um die Objektgruppe jedes Mal zu filtern, sind teilweise vom Benutzer konfigurierbar. Dies bedeutet, dass Benutzer in der Lage sind, die Werte und Bereiche für die Übereinstimmung auszuwählen, aber die Attribute, aus denen sie auswählen können, sind fest.

Die Datensätze enthalten wahrscheinlich für jede Suche & lt; = 10.000 Objekte. Die Suche wird von der Benutzerbasis der Anwendung wahrscheinlich nicht öfter als 2000 Mal am Tag (ungefähr) ausgeführt. Es ist wahrscheinlich erwähnenswert, dass alle Objekte in der Ergebnismenge bekannte Domänenobjektklassen sind, die Hibernate- und JPA-Annotationen haben, die ihre Struktur und Beziehung beschreiben.

Mögliche Lösungen

Abseits meines Kopfes kann ich mir drei Möglichkeiten vorstellen:

  1. Bei jeder Suche werden die ersten Ergebnismengenobjekte in unserer Datenbank beibehalten und dann mit Hibernate erneut mit den feineren Kriterien abgefragt.
  2. Verwenden Sie eine In-Memory-Datenbank (z. B. hsqldb?), um die erste Ergebnismenge abzufragen und zu verfeinern.
  3. Schreiben Sie einen benutzerdefinierten Code, der die erste Ergebnismenge iteriert und die gewünschten Datensätze auslesen kann.

Option 1

Option 1 scheint eine Menge von Hin- und Herlaufen über ein Netzwerk zu einer physischen Datenbank (Oracle 10g) zu beinhalten, was zu einer Menge Netzwerk- und Plattenaktivität führen kann. Es würde auch erfordern, dass die Ergebnisse von jeder Suche von anderen Ergebnismengen isoliert werden, um sicherzustellen, dass verschiedene Suchen sich nicht gegenseitig stören.

Option 2

Option 2 scheint im Prinzip eine gute Idee zu sein, da es mir erlaubt, die feinere Abfrage im Speicher durchzuführen und die Persistenz von Ergebnisdaten nicht erfordert, die erst nach Abschluss der Suche verworfen würden. Ein gutes Gefühl ist, dass dies auch ziemlich performant sein könnte, aber zu größeren Speicherkosten führen könnte (was gut ist, da wir ziemlich flexibel auf die Menge an Speicher sein können, die unsere JVM bekommt).

Option 3

Option 3 könnte sehr performant sein, aber das ist etwas, was ich gerne vermeiden würde, da jeder Code, den wir schreiben, so sorgfältige Tests erfordert, dass die Zeit, die benötigt wird, um etwas flexibel und robust genug zu machen, wahrscheinlich unerschwinglich wäre.

Ich habe keine Zeit, um alle drei Ideen zu entwickeln, also suche ich nach Kommentaren, die Leute zu den drei oben genannten Optionen haben könnten, plus weiteren Ideen, die ich nicht berücksichtigt habe, um mir bei der Entscheidung zu helfen, welche Idee am besten geeignet ist. Ich lehne mich derzeit an Option 2 (in der Speicherdatenbank) an, also würde ich gerne von Leuten hören, die Erfahrung darin haben, POJOs auch im Speicher abzufragen.

Ich habe die Situation hoffentlich ausführlich genug beschrieben, aber zögere nicht zu fragen, ob weitere Informationen erforderlich sind, um das Szenario besser zu verstehen.

Prost,

Edd

    
Edd Grant 18.05.2010, 09:26
quelle

4 Antworten

1

Die Optionen 1 und 2 sind durchaus kompatibel: Durch die Implementierung von eins können Sie es durch einfaches Rekonfigurieren von persistence.xml ersetzen (vorausgesetzt, dass die speicherinterne Datenbank JPA-kompatibel ist, z. B. JavaDB, Derby usw.).

Option 3 re-implementiert sowohl Software von Drittanbietern (Datenbank) als auch Ihren eigenen Code (vorhandene JPA-Entitäten). Sie haben auch seine Vorteile aufgeführt. Es ist eindeutig eine weniger machbare Option in Ihrem Fall. Ich kann mir auch nichts anderes vorstellen, um Option 3 zu fördern.

Es scheint, dass die In-Memory-Datenbank für Anwendungsfälle und deren Zeitspanne besser geeignet ist. Wenn sich Anforderungen in weniger flüchtige ändern, können Sie zu Oracle wechseln.

    
topchef 19.05.2010 05:16
quelle
1

Wenn Ihre Ausdrücke nicht zu komplex sind, können Sie eine Ausdruckssprache zum Bewerten von String-Abfragen auf Ihren Java-Objekten (POJOs) verwenden. Ich kann MVEL Ссылка empfehlen.

Die Idee ist, dass Sie Ihre Objekte in den MVEL-Kontext stellen. Dann geben Sie eine Zeichenkettenabfrage an, die gemäß der einfachen MVEL-Notation geschrieben wurde, und bewerten schließlich den Ausdruck.

Beispiel aus der MVEL-Site:

%Vor%

In der Regel unterstützen Ausdruckssprachen das Durchsuchen des Objektgraphen (Sammlungen) und Zugriff auf Member im JSP-EL-Stil (Punktnotation).

Außerdem kann ich vorschlagen, OGNL zu betrachten (google es, ich kann nicht mehr als einen Link hinzufügen)

    
leopoldkot 21.05.2010 12:45
quelle
0

Wie komplex sind die Verfeinerungskriterien? Wenn die Mehrheit ziemlich einfach ist, würde ich versucht sein, zuerst die Option (3) zu wählen, aber stellen Sie sicher, dass sie hinter einer geeigneten Schnittstelle gekapselt ist, so dass Sie, wenn Sie etwas zu komplex oder ineffizient finden kann zu diesem Zeitpunkt in den In-Memory-DB wechseln (entweder für alle Abfragen oder nur für die komplexen, wenn beim Einrichten der temporären Tabellen ein Overhead entsteht).

    
pdbartlett 18.05.2010 11:20
quelle
0

Option 2 scheint gut zu sein - da Sie zwischen 1 & amp; 2 nach Bedarf. 3 ist in Bezug auf die zukünftige Dimensionierung der Daten ebenfalls eingeschränkt. Das Abfragen von Objekten würde eine größere Abhängigkeit von der Codestruktur für das Speichern und Abfragen nach sich ziehen.

Wahrscheinlich wäre es eine gute Idee, einen Caching-Mechanismus (ehcache / memcache) zusammen mit Option 2 einzufügen und dann ein Profiling durchzuführen, um den Leistungsunterschied zu überprüfen.

    
techzen 19.05.2010 08:11
quelle