Architektur einer schreibintensiven Funktion

8

Ich verwende Ruby auf Rails, die von der Oracle-Datenbank unterstützt werden, und memcached für mein aktuelles Projekt.

Es gibt eine ziemlich stark genutzte Funktion, die auf einer einzigen Datenbanksicht als Datenquelle beruht, und diese Datenquelle enthält intern andere Datenbankansichten und -tabellen.

Es ist eine virtuelle Datenbankansicht, um auf alles von einem Ort aus zugreifen zu können, nicht auf eine materialisierte Datenbankansicht.

Benutzer die meiste Zeit, wenn sie in der Funktion sind, die sie aktualisieren möchten, so dass Daten auf dem neuesten Stand ist wichtig.

Beim Abrufen von Daten aus dieser Ansicht verbinde ich die Sicherheitstabelle mit der Ansicht (die Sicherheitstabelle ist nicht Teil der Ansicht selbst), die einige Felder enthält, mit denen wir den Datenzugriff auf einer detaillierteren Ebene steuern. Zum Beispiel hat die Sicherheitstabelle user_id, prop_1, prop_2 Spalten, wobei prop_1, prop_2 Spalten sind, die in einer Datenbankansicht verfügbar sind, und user_id ist ein angemeldeter Benutzer. Einige Benutzer haben die gleichen Requisiten in der Sicherheitstabelle sagen prop_1 = 1 and prop_2 = 1 , aber können auch prop_1 wie der andere Benutzer haben aber andere prop_2 wie prop_1 = 2 and prop_2 = 1 . Es gibt viele verschiedene Kombinationen von prop_1 und prop_2, denke über sie als FK an eine andere Tabelle, so dass viele Einträge möglich sind.

Inzwischen ist die Zeit, um die Datensätze in der App abzurufen, fast 10 Sekunden, es ist ziemlich langsam. Ich denke über alternativen Ansatz nach.

Als erstes habe ich die materialisierte Ansicht gefunden, aber da der Benutzer häufig Aktualisierungen vornimmt, ist dies möglicherweise nicht die beste Wahl, da das Aktualisieren der Ansicht einige Zeit dauern kann.

Zweitens habe ich über den Cache nachgedacht, um prop_1 und prop_2 combination als zusammengesetzten Schlüssel für die zugrunde liegenden Daten zu verwenden, da viele Benutzer dieselbe Kombination haben und wer dieselbe Kombination hat, kann auf dieselben Daten zugreifen.

Allerdings erfordert dieser Ansatz möglicherweise mehr Code-Umschreibungen und Logik, um Daten in Fragmenten zu speichern und abzurufen, und zwar von einem Ort mit einer Abfrage wie in der Datenbankansicht.

Wie haben Sie in Ihrer Erfahrung das gleiche / ähnliche Problem angesprochen? Oder gibt es einen besseren Ansatz, den ich ausprobieren könnte?

Für diejenigen, die fragen wollen, was haben Sie versucht? Ich denke zuerst über die Lösung nach, sammle Informationen von verlässlichen Ressourcen und erfahreneren Leuten, dann werde ich eine informierte Entscheidung treffen und mit der Umsetzung beginnen. Das erste zu implementieren, das zweite nachzudenken, hat sich so oft als falsch erwiesen.

    
Gandalf StormCrow 24.06.2016, 11:44
quelle

4 Antworten

1

Es ist schwer, eine gute Antwort ohne weitere Informationen über Ihre Sicht zu geben, aber ich werde es versuchen.

Zunächst stelle ich die Verwendung einer einzigen sehr komplexen Sichtweise in Frage. Das ist schwer zu tunen und kann oft zu Performance-Problemen führen. Wenn es möglich ist, es in der Anwendung zu teilen, wäre das meine erste Wette.

Zweitens, haben Sie sich den Ausführungsplan (Explain Plan) für die Abfrage mit den enthaltenen Sicherheitsfiltern angesehen? Verwendet es sinnvolle Indizes? Wenn nicht, erstellen Sie sie. Vielleicht sind die Sicherheitseigenschaften nicht indiziert, zum Beispiel?

Eine dritte Option könnte sein, PL / SQL zu verwenden und eine gespeicherte Prozedur aufzurufen, die wie die Ansicht funktioniert. Das gibt Ihnen mehr Kontrolle in der Datenbank, die es ermöglicht, die Abfrage zu steuern und in mehrere Schritte zu teilen, aber das gleiche Ergebnis wie heute zu erhalten.

Schließlich können Sie die Ansicht möglicherweise für eine bessere Leistung neu schreiben. Ein häufig übersehenes Feature ist die WITH-Klausel, die es ermöglicht, eine Abfrage vor der Hauptabfrage auszuführen und das Ergebnis als Tabelle zu verwenden. Es hat mir geholfen, die Leistung für komplexe Ansichten dramatisch zu verbessern.

DBMS_RLS ist cool, kann aber teuer sein, es erfordert die Enterprise Edition und es würde mich nicht überraschen, wenn Sie auch eine separate Lizenz benötigen. Ich würde zuerst eine programmatische Lösung wählen.

    
user2612030 01.07.2016 14:55
quelle
1

Wenn Sie wahrscheinlich einige Latenzzeiten für Ihre Datenbank erleiden, können Sie einige Ihrer Ansichten in eine REDIS-Datenbank migrieren (In-Memory-Daten) Strukturspeicher), der wahrscheinlich einer der effizientesten im "Lesen / Schreiben" -Intensivieren ist.

In Bezug auf das Update-Problem können Sie einen Websocket implementieren, um präzise Updates direkt an diejenigen zu verteilen, die sie benötigen.

Ich unterstreiche, dass diese Möglichkeit einige Änderungen sowohl bei Client & Amp; Server-Seiten, aber ich gehe davon aus, dass es der beste Ansatz ist, die endgültige Benutzeransicht mit geringer Latenz aktualisiert zu halten.

Mit freundlichen Grüßen

    
A STEFANI 05.07.2016 11:46
quelle
0

Oft stellt die Verbindung zu einer komplexen Ansicht Performance-Probleme dar.

Sind prop_1 und prop_2 Werte, auf die Sie beschränken möchten? Das heißt, verbinden Sie Ihre Ansicht mit der Sicherheitstabelle für diese Spalten, wie

%Vor%

?

Nächste Frage: Stellen prop_1 und prop_2 auf Spalten in den zugrunde liegenden Tabellen der Ansicht ab? Wenn ja, können sie verwendet werden, um auf Zeilen aus den zugrunde liegenden Tabellen schnell (außerhalb Ihrer Sicht) zuzugreifen?

Wenn ja, würde ich versuchen, DBMS_RLS.ADD_POLICY add Sicherheitsrichtlinien für die zugrunde liegenden Tabellen zu verwenden, um Ihre Sicherheit zu erzwingen (dh die Grenzwerte von prop_1 und prop_2 basierend auf dem aktuellen Benutzer) und der Sicherheitstabelle nicht beizutreten die Aussicht überhaupt.

Wenn Sie den zugrunde liegenden Tabellen Sicherheitsrichtlinien hinzufügen, fügt Oracle diese Prädikate beim Zugriff auf die Tabellen hinzu, bevor die Komplexität Ihrer Abfrage beginnt. Das könnte dem Oracle-Optimierer die zusätzliche Hilfe geben, die er benötigt, um den Prozess zu beschleunigen.

Ohne Ihren Code zu sehen, ist es schwierig, mehr zu sagen.

    
Matthew McPeak 28.06.2016 21:21
quelle
0
  

"stützt sich auf eine einzelne Datenbankansicht als Datenquelle, und diese Datenquelle enthält intern andere Datenbankansichten und Tabellen."

Wenn das ein Objekt wäre, würden wir es ein Gott-Objekt nennen, was eine schlechte Sache ist. Es ist genau so ein Anti-Pattern im Bereich der Datenbank. Ohne die Details zu kennen, ist es schwer sicher zu sein, aber wahrscheinlich haben Sie ein Durcheinander von inneren Joins, Outer Joins und Cross Joins, was zu De-Normalisierung, Datenduplikation und (vielleicht) Integritätsproblemen führt.

Sicher haben Sie Performance-Probleme, die unvermeidbar sind, weil so etwas nicht einstellbar ist. Ob Sie eine Zeile oder zehntausend Zeilen möchten, es ist die gleiche Abfrage. Sie geben dem Optimierer nicht die Möglichkeit, vernünftige Entscheidungen zu treffen.

Als erstes müssen Sie diese Ansicht in aussagekräftige Datenobjekte (Ansichten oder Tabellen) aufteilen, die auf bestimmte Geschäftsbereiche ausgerichtet sind. Sie verwenden bereits Rails, es sollte nicht so schwer sein, eine bessere Datenzugriffsschicht zu verwalten.

Aus Sicherheitsgründen verfügt Oracle über eine integrierte Virtual Private Database-Implementierung. Wenn Sie Enterprise Edition verwenden, sollten Sie definitiv DBMS_RLS verwenden, um den Zugriff auf Zeilenebene (und Spaltenebene) zu steuern. Der Hauptvorteil von RLS ist, dass es unsichtbar ist: Legen Sie eine Richtlinie für eine Tabelle oder Sicht fest, und sie wird automatisch auf alle SQL angewendet, die für das Objekt ausgeführt werden.

Wenn Sie mit der Standard Edition arbeiten, müssen Sie explizite Joins für Ihre Sicherheitstabelle verwenden (siehe unten).

Was die Verwendung von memcached anbelangt, neigen Anwendungsentwickler nach meiner Erfahrung dazu, externe Caches zu erstellen, weil sie nicht verstehen, wie Oracle-Datenbanken funktionieren, und so schlechte Datenzugriffsstrategien implementieren - zum Beispiel alles durch eine einzige monströse Ansicht zu routen. ..

Wenn Sie Ihre DAL in diskrete, aussagekräftige Objekte aufteilen, erhalten Sie eine bessere Leistung, da der Datenbankoptimierer in der Lage ist, den effizientesten Pfad zum Extrahieren der benötigten Informationen auszuwählen. Auch die Retrieval-Pfade werden besser sein, weil die heißen (am häufigsten abgefragten) Blöcke Hilfe im Datenbank-Puffer-Cache sein werden, während ich im Moment vermute, dass dies durch einen Überschuß von vollständigen Tabellen-Scans vollkommen zerstört wird. Sie können das Serverergebnis-Caching nutzen, das dabei helfen könnte, dass "Benutzer dieselbe Kombination haben und [wer] auf dieselben Daten zugreifen kann" Erfahren Sie mehr .

Sie werden also möglicherweise feststellen, dass Sie keinen externen Cache benötigen. Sicherlich, indem Sie die Datenbank ihre Daten richtig verwalten lassen - mit Technologie entsprechend - sollten Sie feststellen, dass Sie viel weniger externe Daten benötigen. Sie beschreiben Ihre Anwendung als "schreibintensiv", so dass Sie viele Zyklen benötigen, um den Cache und die Datenbank synchron zu halten. Natürlich, wenn Sie mit Facebook Datenmengen zu tun haben, müssen Sie Facebook Stil Ansätze zur Datenverwaltung verwenden. Aber im Allgemeinen ist Die einfachste Sache, die möglicherweise funktionieren kann , der beste Ausgangspunkt.

    
APC 05.07.2016 07:13
quelle