![]() |
Datenbank: PostgreSQL • Version: 8.4.1 • Zugriff über: PHP / pgAdmin direkt
Geschwindigkeit von Views verbessern
Hiho!
Ich habe eine Datenbank welche unter anderem folgende Tabellen ethält: o Mandantenstamm o Zugriffsteuerung (Benutzer -> Mandant) o Datentabelle ... Nun habe ich eine View für die Datentabelle erstellt, welche nur noch die Daten anzeigt, welche mich (also "current_user") auch betreffen (passend zu der Tabelle Zugriffssteuerung) und das Ganze funktioniert an sich auch einwandfrei. Das Problem dabei ist aber, dass die Datentabelle div. Millionen Datensätze beinhaltet. Dadurch dauert das Öffnen der View bestimmt 1 Minute, was natürlich absolut untauglich ist. Sinngemäßes SELECT Kommando, welches hinter der View liegt:
SQL-Code:
...
SELECT d.* FROM datentabelle d, zugrifftabelle z WHERE d.mandant = z.mandant
Wie gesagt: logisch ist das vollkommen richtig so. Nur von der Geschwindigkeit her absolut inakzeptablel. Hat einer von Euch ne Idee, wie man so eine Lösung schneller regeln kann, als über so eine WHERE-Abfrage? Danke im Voraus Patrick |
Re: Geschwindigkeit von Views verbessern
Hast Du die Spalte Mandant in der Datentabelle indiziert? Wenn nicht, mach's mal.
Uli |
Re: Geschwindigkeit von Views verbessern
Indizes vorhanden?
Hat der Server genügend Speicher zur verfügung das diese Indizes auch komplett im Speicher gehalten werden können? |
Re: Geschwindigkeit von Views verbessern
Indizes sind 2 Stück vorhanden.
1x auf die Mandanten-Spalte alleine und 1x noch etwas genauer (mit Zeitraum und Co.) ... Das mit dem Speicher ist aber nen guter Tipp, da hat mich auch ein Kollege gerade drauf gebracht! Weil das ist eine neu aufgesetzte Datenbank und da hab ich noch nix an den Einstellungen von Postgres selbst gedreht. Vielleicht bringt das was, wenn ich da mal die Speicherbereiche vergößer. Ich probier es mal aus. |
Re: Geschwindigkeit von Views verbessern
Hi,
ich tippe eher auf das Statement. Die Indexe werden ja scheinbar nicht benutzt. Möglicherweise hilft ja schon eine Umstellung von dem where auf ein left join. Frank |
Re: Geschwindigkeit von Views verbessern
Brauchst du zudem alle Felder?
|
Re: Geschwindigkeit von Views verbessern
Wenn ich die Abfrage via pgAdmin analysieren lasse scheint er den Index in der Tat nicht zu nutzen.
Das macht er nur, wenn ich die Mandantennummer direkt eintrage. Sobald ich diese aber aus der anderen Tabelle mit einbeziehe scheint er den zu übergehen. Hm... Ich probier mal rum, wie ich das umgehen kann. ... Felder brauche ich übrigens alle, denn diese View weiß nicht wofür sie gebraucht wird. Die ist nur dafür da, dass ich selbst als DB-Benutzer nur das sehen kann, was mich auch zu interessieren hat, völlig unabhängig davon, welches Programm es nacher wie nutzen wird. Ich möchte so gesehen die Sicherheitslogik / Datentrennung schon auf Datenbankebene haben und nicht erst auf Applikationsebene. |
Re: Geschwindigkeit von Views verbessern
Ach ja, nochwas: Mio. Datensätze? Schon mal ausgerechnet wieviel MB hier über Netz geschaufelt werden müssen (Clientseitiger Curse vorrausgesetzt) oder wieviel Speicher der Server für den serverseitigen Curser reservieren muss?
|
Re: Geschwindigkeit von Views verbessern
Zitat:
Die kompletten Daten werden also niemals gebraucht. Das geht hierbei wirklich um eine reine Datensicherheits / -Berechtigungsgeschichte. Wir wollen nicht, dass es ÜBERHAUPT irgendeinem Datenbankbenutzer möglich ist SELECT Abfragen direkt auf die Tabellen zu starten. Dies soll immer nur über Views geschehen, die per se nur das anzeigen, was den Benutzer zu interessieren hat. Abfragen auf die Tabellen selbst darf nur der Admin und der ist so eingestellt, dass sich dieser nur von Managementsystemen verbinden darf und nicht von den eigentlichen Produktivsystemen. (Später auch noch nicht mal mehr vom Localhost). ... Von daher muss ich das Grundprinzip schon so lassen und da führt auch (meines Wissens nach) kein Weg dran vorbei. Bei allen anderen Datentabellen funzt das auch einwandfrei, auch vom Tempo her. Aber die haben auch nur ein paar Hundert bis evt. Zehntausend Datenzeilen und nicht wie diese eine div. Millionen. |
Re: Geschwindigkeit von Views verbessern
Benötigst du wirklich alle Rechte aller Benutzer?
|
Re: Geschwindigkeit von Views verbessern
Hi!
Mit deiner Anweisung
SQL-Code:
liest du alle Datensätze aus der Datentabelle, das dauert bei Millionen von Datensätzen natürlich einige Zeit. Die Angabe der Zugrifftabelle im FROM-Teil - und damit auch das WHERE-Token bewirken gar nichts mehr, da ja aus z keine Felder selektiert werden und die WHERE-Klausel die Datensätze von D nicht einschränkt.
SELECT d.* FROM datentabelle d, zugrifftabelle z WHERE d.mandant = z.mandant
Vermutlich willst du ja nur die Daten zu "current_user" anzeigen. Wenn dies ein Feld der Zugriffstabelle ist, solltest du die SQL-Anweisung so ändern:
Delphi-Quellcode:
query.SQL := 'SELECT d.* FROM datentabelle d '
+'LEFT JOIN zugriffstabelle z on d.mandant=z.mandant ' +'WHERE z.current_user='''+aktuser+''''; |
Re: Geschwindigkeit von Views verbessern
Zitat:
Der Sinn dieses Patentes is ja, dass eben kein einziger Benutzer alle Rechte hat, sondern jeder nur "seinen" Teil der Daten sieht. Und das schon direkt auf Datenbankebene und nicht erst durch die Applikation geregelt. Von daher weiß ich jetzt leider nich so recht, was Du mit "alle Rechte aller Benutzer" meinst. :oops: |
Re: Geschwindigkeit von Views verbessern
Delphi-Quellcode:
wenn Du nur "Deine" Datensätze sehen willst, dann solltest Du das der DB auch mitteilen.
where d.mandant='ich'
Gruß K-H |
Re: Geschwindigkeit von Views verbessern
Mein Tip bei so einer sicheren Trennung der Tabellen vom Benutzer ist die Verwendung von SP = Stored Procedures.
(wer es noch nicht wissen sollte, eine SP kann auch Datensätze zurückliefern ;) ) Zumal man bei einer SP auch Parameter übergeben kann, die den SELECT auch gleich einschränken. Beispiel: hole_mal_daten( <Mandant>, <ZeilenProSeite>, <Seite> ) Mit so einer SP halt man sich nur eine bestimmte Anzahl von Zeilen und kann durch verändern der Seitenzahl schön durchblättern. In der SP kann ich dann die ganze Filterung reinbauen, damit auch nur diese Daten kommen. Auch das Schreiben von Daten lässt man über SP's laufen. Dann kann man den Benutzer getrost von den Tabellen abklemmen. Aber eine View dafür zu benutzen ist doch sehr ressourcenfressend (wie du ja auch siehst). cu Oliver |
Re: Geschwindigkeit von Views verbessern
Zitat:
Zitat:
|
Re: Geschwindigkeit von Views verbessern
So, hab gerade mal die Speichergrenzen von Postgres etwas erweitert (div. Einstellungen verdoppelt) und prompt braucht die Abfrage nur noch ca. halb so lange.
Ein vervierfachen hat dagegen dann allerdings nichts mehr gebracht. Bzw. Abfrage ist ja nicht ganz richtig, denn das Öffnen der View im pgAdmin dauert jetzt nur noch halb so lange. Die letztendliche Abfrage des Programms á la "SELECT * FROM datenview WHERE monat="" AND ..." dauerte ja eh nur ein paar Sekunden und nicht die volle Minute. Ist aber jetzt auch ne Ecke schneller als vorher. Von daher schien das echt was zu bringen. ... Des Weiteren ist uns noch eingefallen, dass wir den Datenbestand als solches noch etwas reduzieren können, da wir in der eiegentlichen Datentabelle gar nicht erst alles brauchen, was da im Moment gepflegt ist. Dadurch sollte die View dann ja auch wieder schneller werden. ... Zu den Stored Procedues: Das ist ja nicht ganz das was ich möchte, denn somit überlasse ich die Trennung welcher DB-Benutzer was sehen darf letztendlich wieder der Applikation die sagt "funktion('meinMandant')"; Es wäre da aber technisch gesehen genauso möglich zu sagen "Funktion('EinAndererMandant')" und das würde trotzdem funktionieren. ... Das gleiche gilt für den Vorschlag von p80. Wenn ich die Trennung selbst mache (also in der Applikation oder allg. via SQL), dann bräuchte ich diesen ganzen Heckmeck gar nicht mehr betreiben. ... @Bernhard Mit "filterung clientseitig" war das obig geschrieben Select-Kommando gemeint. Also die Daten fließen definitiv NICHT über das Kabel, bevor sie gefiltert werden, sondern das passiert schon auf DB-Seite. Und zum zweitem Abschnitt: Genau darum ging es mir ja bei dieser ganzen Thematik. Selbst wenn ich jetzt in der Lage bin, Clientseitig beliebige SQL-Kommandos zu erzeugen und abzusetzen, bin ich durch meine View trotzdem nicht in der Lage alle Daten zu sehen, da in der View per se und immer nur die Daten angezeigt werden, welche mich gerade betreffen. Da nützt dann auch kein SQL Kommando "SELECT * FROM view WHERE mandant='EinAnderer'" was, denn diese Daten sind in der View schlicht und einfach nicht vorhanden. Und auf die letztendliche Datentabelle hat wie gesagt nur der Admin zugriff und der darf sich gar nicht erst von der Clientseite her anmelden, da wird schon die Anmeldung verweigert. |
Re: Geschwindigkeit von Views verbessern
Zitat:
So eine SP kann man auch intelligent aufbauen. In der SP wird z.B. der SQL-Benutzer mit ausgewertet ... was darf der sehen Oder gib als zusätzliche Parameter einen Benutzernamen und das Passwort (als MD5-Hash) mit und mach daran die Selektion fest. Eine SP darf durchaus intelligent funktionieren :mrgreen: cu Oliver |
Re: Geschwindigkeit von Views verbessern
Zitat:
Ja ist es, weil in der View nur die Daten meiner Mandanten drin sind. Ganz ohne SQL-Abfrage, Where-Klausel, Parameter oder sonst was. Die View weiß also von Haus aus, wer sie öffnet (postgres-funktion current_user) und was dieser sehen darf ;) @2 Ok, wenn man das so macht hast Du natürlich Recht. Aber diese doppelt- und dreifach-überprüfung entfällt in meinem Falle halt komplett, weil das die View das schon intern regelt. Das was Du geschrieben hast ist ja fast(!) das was mein Programm vorher PHP-Seitig gelöst hat. Da wurde auch alles immer gegeneinander geprüft und verglichen. Nur das man es quasi von PHP auf DB Ebene verschoben hätte. ... Das brauche ich jetzt aber eben eigentlich gar nicht mehr. Denn ich bin wie gesagt auf Datenbankebene schon so eingeschränkt, dass ich nicht an die Daten anderer Mandanten (und darum gehts ja) komme. Dafür muss ich direkt auf die Datentabelle und das darf ausser dem Admin keiner. (Oder ich schaffe es mich als anderer Datenbankbenutzer anzumelden, aber dagegen kann man dann eh nix machen). |
Re: Geschwindigkeit von Views verbessern
Ich glaube wir sprechen gerade aneinander vorbei :mrgreen:
SQL-Code:
Du lieferst über dein View (s.o. mal als Beispiel) alle Daten, die der aktuelle Benutzer sehen darf und schränkst diese dann auf dem Client ein.
SELECT * FROM foo WHERE user = current_user
Das dauert, weil dafür auf dem Server Speicher reserviert werden muss (viel) und dann müssen alle Daten an den Client gesendet werden (viel und dauert deshalb so lange).
SQL-Code:
Nimmst du eine SP, dann übergibst du mit dieser SP die Einschränkungskriterien. In der SP wird der gleiche SELECT wie in deiner View ausgeführt, nur zusätzlich mit den übergebenen Einschränkungen (Parameter der SP s.o.).
SELECT * FROM foo WHERE user = curent_user AND field1 = Einschraenkung
Der Server muss jetzt nicht mehr so viel Speicher reservieren und auch nicht mehr so viele Daten an den Client senden. Somit geht das alles flotter, bei gleicher Sicherheit. |
Re: Geschwindigkeit von Views verbessern
Kannst du ein etwas realistischeres Beispiel geben?
das SQL von ersten Post macht ja reichlich wenig sinn:
SQL-Code:
IOW: Gebe mir x-mal die gleichen Rows aus d, schließlich wird z.mandant nicht eindeutig sein, oder? Und selbst wenn, wo ist denn da die Einschränkung?
SELECT d.* FROM datentabelle d, zugrifftabelle z WHERE d.mandant = z.mandant
Oder dachtest du an sowas?
SQL-Code:
Aber mal abgesehen davon, halte ich das für eine grauenvolle Idee...
SELECT d.*
FROM Datenzeugs d INNER JOIN UserPrivileges up on up.Privilege = d.RequiredPrivilege where up.UserName = Current_User() Direkten Zugriff auf die DB (nicht nur auf die Tabellen) sollte gar kein Normalsterblicher haben. Wir schreiben fast 2010, nicht 1989. Klassische C/S Systeme in Bereichen wo man sich um Sicherheit und Zuverlässigkeit sorgen muss sind doch nun wirklich mehr als ausgedient. Ist Zugriff für generische Reporting Tools (Crystal, etc) nötig, dann kann man sich zum Beispiel einen Simple-Mode OleDB Provider bauen. Oder einfach Reporting als Zusatzfeature mit anbieten. Dann geht das alles geregelt durch den Appserver und nicht daran vorbei in die DB. Der Server wird stets und ständig aus allen Löchern pfeifen und er wird schneller einen Punkt erreichen, bei dem du noch soviel Hardware danach schmeißen kannst. Du wirst einfach nicht weiter skalieren können, wenn du mit solchen Views den Query-Optimizer boykottierst. Und das wiederum heißt, dass deine App ein Mindesthaltbarkeitsdatum auf dem Deckelrand gedruckt hat, ab dem man eine neue App brauchen wird, da diese irgendwann mit den wachsenden User und/oder Daten nicht mehr standhalten können wird. |
Re: Geschwindigkeit von Views verbessern
Wenn in der View viele self joins vorhanden sind, oder allgemein sehr viele Tabellen verknüpft werden, versagt so ziemlich jeder Query-Optimizer. Selbst wenn Du jetzt dieses Problem durch Speichereinstellungen gelöst hast, wirst du später irgendwann an die Grenzen stoßen, die sich dann nicht mehr erweitertn lassen.
Neben Stored Procedures bieten sich auch Functions an. Rein konzeptionell würde ich Funktionen vorziehen, denn eine Funktion liefert ja etwas (z.B. eine Tabelle), während eine Prozedur etwas auslöst bzw. bewirkt. Der prinzipielle Aufbau wäre dann: 1. Definiere Resultattabelle 2. Befülle die Tabelle mit dem PK sowie dem ersten Teil an Daten (z.b. max 8x JOIN, muss man ausprobieren) 3. Befülle die Tabelle mit dem nächsten Block 4. Usw N. Liefere die Daten |
Re: Geschwindigkeit von Views verbessern
Hallo,
was ihr alle gegen Views habt ??? ;) Hier mein Senf. *gr* SELECT d.* FROM datentabelle d, zugrifftabelle z WHERE d.mandant = z.mandant sollte auf jeden Fall umgeschrieben werden. SELECT d.* FROM datentabelle d INNER JOIN zugrifftabelle z on d.mandant = z.mandant Auf datentabelle.mandant und zugrifftabelle.mandant müssen Indizes liegen. Die Indizes müssen "aktuell" sein (ausbalanciert) Unter Firebird geht das mit Alter Index Inactive / Alter Index Active unter PostgreSQL ??? #Update#, ANALYZE heisst das wohl. Das ich als Client nicht mit Select * From View auf den View gehe und dann alle Daten am Stück laden, ist genauso klar wie es bei Tabellen ist. Warum der Query-Optimizer bei der Verwendung von Views Probleme bekommen soll, ist mir nicht ganz klar, es sei denn du meinst Views mit vielen Joins. Wenn ein User solche Views auch noch verjoint, gibt das natürlich etwas Arbeit für den Optimizer. Hier noch ein paar interessante Links. Du solltest dir mal besionders Partitionierung ansehen. ![]() ![]() Heiko PS: An dem OpenSource-Tag war ich dabei ;) |
Re: Geschwindigkeit von Views verbessern
Das ändert aber nichts daran, dass alle Rechte aller Benutzer abgefragt werden, obwohl er nur die Rechte eines Benutzer benötigt
|
Re: Geschwindigkeit von Views verbessern
Hallo,
nun der View sollte natürlich auch anständig, also effektiv, definiert sein. Heiko |
Re: Geschwindigkeit von Views verbessern
Zitat:
Wenn ich meine komplette Struktuer hier aufzeichne, habe ich gleich doppelt so viele Tabellen. Echte Tabellen benutzertabelle mandantentabelle zugriffstabelle datentabelle Views: benutzer_effektiv mandanten_effektiv zugriff_effektiv daten_effektiv ... Ich habe also für jede Tabelle (egal ob Mandant, Daten, Benutzer, Zugriff oder sonst was) eine View auf der ich jeweils nur die Daten sehe die mich betreffe und nur darauf bastelt der User rum. Und bei den tiefer gehenden Views baue ich logischerweise schon auf den vorherigen Views auf. Also heißt es konkret nicht
SQL-Code:
sondern
"Select d.* from datentabelle d, zugriffstabelle z WHERE d.mandant = z.mandant"
SQL-Code:
Das war ja nur ne vereinfachte Darstellung.
"Select d.* from datentabelle d, zugriff_effektiv z WHERE d.mandant = z.mandant"
... Und zu der ständigen Aussage "Weg von Client/Server Technolige, wir ham 2009 nich 1990, mach dies, tu das". Wie soll ich das denn bei einer PHP-Anwendung machen? Das ist doch prinzipbedingt eine C/S Anwendung, oder sehe ich das falsch? |
Re: Geschwindigkeit von Views verbessern
Deine Abfrage ist trotzdem ein Inner Join über die beiden Tabellen, also alle Rechte aller Benutzer!
|
Re: Geschwindigkeit von Views verbessern
Zitat:
Wenn ich nun die Generierung der Resulttabelle aufteile, dann klappt es mit dem RAM wieder und ich bekomme 1-fix-3 mein Ergebnis. Ich finds auch blöd, solche Workarounds zu basteln, aber leider kommt man manchmal nicht drumherum. |
Re: Geschwindigkeit von Views verbessern
Zitat:
Oracle lauft unter ..ix Gruß K-H |
Re: Geschwindigkeit von Views verbessern
Hallo,
bei MS-SQL muss man den maximalen Speicher manuell festlegen, sonst verbrät der alles. Heiko |
Re: Geschwindigkeit von Views verbessern
Zitat:
Zitat:
Ich bezog mich bei C/S darauf, dass dabei der User direkten Zugriff auf die DB hat, und man deshalb so abartige Vergewaltigungen von RDMS-Features und Serverhardware braucht, um sich gegen diese Zugriffe des Users abzusichern. Deine PHP Page wird ja selbst Zugangskontrolle ausüben, also warum denn das ganze NOCHMAL innerhalb der DB machen? Will heißen, du sorgst doch in dem PHP-Server schon dass User X nur Dinge sehen/machen darf, die er auch wirklich sehen/machen darf. Warum willst du denn jetzt zusätzlich eine weitere Kontrolle einbauen, die dich dann immer und überall CPU-Zyklen, Speicher und vernünftige Querypläne kostet? |
Re: Geschwindigkeit von Views verbessern
Zitat:
Wenn ich bei MySQL in einer function einen SELECT * FROM foo schreibe, dann meckert MySQL schon bei der Anlage der Function. Bei einer Procedure funktioniert das. |
Re: Geschwindigkeit von Views verbessern
Eine UDF ist meines Erachtens was anderes als eine SP.
|
Re: Geschwindigkeit von Views verbessern
Zitat:
Zitat:
Zitat:
Ich denke, man muss auch bei MySQL (wenn es denn das Konzept vorsieht) in einer Funktion einen Funktionstyp definieren (Zahl, String, Tabelle o.ö) und dem Resultat dann etwas zuweisen. Falls MySQL diesbezüglich eine Einschränkung hat, und z.B. nur generische Datentypen als Funktionstyp erlaubt, dann wäre das peinlich, aber nicht zu ändern. Ich sprach im Übrigen von Konzepten. Eine Funktion berechnet etwas und liefert es zurück (oder transformiert oder was auch immmer), eine Prozedur nicht, die macht etwas. Das man in einer SP auch 'SELECT' schreiben kann, ändert nichts an diesem Paradigma. |
Re: Geschwindigkeit von Views verbessern
Eine Funktion liefert aber einen Wert zurück und keine Datenmenge. Eine SP kann auch eine Datenmenge zurückliefern. Deshlab ist sie imho in diesem Fall besser geeignet.
In Pascal könnte man eine Funktion als Prozedur mit Rückgabe beschreiben, bei einem DBMS stecken da verschiedene Konzepte dahinter. |
Re: Geschwindigkeit von Views verbessern
Zitat:
Ich meine jedoch, das (z.B.) Firebird eine Syntax à la
SQL-Code:
erlaubt. Somit stopfen sie Dataset-UDF und Stored-Procedures unter einen Hut. Das kommt dann aufs Gleiche raus und ist ok.
SELECT * FROM StoredProcedure (foo,bar)
Was ich gar nicht mag sind Stored Procedures, die man mit 'EXEC' aufruft, und die dann eine Ergebnismenge liefern. Wie soll man da denn Filtern bzw. das Ergebnis weiterverarbeiten? |
Re: Geschwindigkeit von Views verbessern
Nein, das gezeigte ist eine SP. Eine UDF ist in FB in einer Hochsprache implementiert, eine SP (noch) ausschliesslich als SQL-Code. Eine UDF liefert deshalb auch nur Werte zurück, da sie ja eine Funktion in einer Dll/so ist.
SQL-Code:
Select Funktion( <Parameter> from ...
|
Re: Geschwindigkeit von Views verbessern
Zitat:
Und falls es dem potenziellen Angreifer trotz div. Abfragen im PHP selbst, doch noch mal gelingen sollten den Schritt zur SQL-Injection oder vergleichbarem gehen zu können, möchte ich halt auch auf DB Seite so weit sein, dass er auch in dem Falle nicht in der Lage ist, eine komplette Benutzerliste z.B. auslesen zu können. Das kann in meinem System (es sei denn ich habe was übersehen) nämlich keiner ausser dem Admin. Deshalb ja auch dieser ganze Heck-Meck mit Views auf Views auf Tabellen und Co. :D |
Re: Geschwindigkeit von Views verbessern
Zitat:
Zitat:
Gleichzeitig kann die SP auch einen Datenmenge liefern (wie oben erläutert). Brauche ich nur die Parameter-Übergabe und die Datenmenge ist für mich uninteressant, dann führe ich diese mit ExecSQL aus. Benötige ich auch die Datenmenge, dann öffne ich die SP mit OPEN. Jetzt kann ich die Rückgabe-Parameter auslesen und auch das DataSet verarbeiten. cu Oliver |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:42 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz