Oracle DB: mind. 7 aufeinanderfolgende Zeichen aus x sollen in y vorkommen ...
MudGuard
- datenbank
Hi,
ich habe eine Spalte dbspalte, die einen String von bis zu 40 Zeichen (Nur ASCII-Ziffern und ASCII-Buchstaben) enthält.
Desweiteren habe ich einen identisch aufgebauten (also bis zu 40, nur Ziffern/Buchstaben) Eingabestring.
Gefunden werden sollen die Zeilen in der Tabelle, in deren betroffener Spalte 7 aufeinanderfolgende Zeichen mit 7 aufeinanderfolgenden Zeichen aus dem Eingabestring übereinstimmen (jeweils an beliebiger Stelle).
Also z.B.:
db: abcdefghij eingabe: qqqcdefghixxx ⇒ Treffer (cdefghi paßt)
db: abcdefghij eingabe: qqqcdefyyyghixxx ⇒ kein Treffer (cdef und ghi passen zwar, aber die 7 Zeichen sind nicht aufeinanderfolgend)
Ja, ich weiß, das klingt seltsam - ich bin auch gegen die Implementierung dieses "Matching", aber ich will zumindest mal schauen, ob es eine brauchbare technische Lösung gibt.
Spontan fällt mir da für die Implementierung erst mal nur ein: prüfen, ob die Stellen 1 bis 7 des Eingabewerts in der dbspalte im Syncache vorkommt oder ob die Stellen 2 bis 8 des Eingabewerts in der dbspalte im Syncache vorkommt oder ob die Stellen 3 bis 9 des Eingabewerts in der dbspalte im Syncache vorkommt oder ob die Stellen 4 bis 10 des Eingabewerts in der dbspalte im Syncache vorkommt oder ob ... oder ob die Stellen n-6 bis n des Eingabewerts in der dbspalte im Syncache vorkommt
Daß da je nach Eingabewert-Länge unterschiedlich viele "oder" vorkommen, wäre kein Problem, die Query wird vom Programm erzeugt.
Aber das "kommt in x vor" zerlegt die Nutzung des Index. (wobei die Index-Nutzung bei OR auch oft verweigert wird).
Hat jemand eine Idee, wie man das besser realisieren kann?
Grad kommt mir noch eine - aber ist das schon das Optimum?
Regex Find mit (1bis7|2bis8|...|n-6bisn)
.
Dürfte auch nicht wirklich performant sein (braucht vermutlich auch einen Full Table Scan).
Hat noch jemand ne Idee? (darf auch in Mysql- oder Postgres-Syntax sein, ggf. such ich dann halt die Oracle-Entsprechungen)
cu,
Andreas a/k/a MudGuard
Hallo Andreas,
das ist auf jeden Fall ein Full Table Scan. Dass ein OR generell dazu neigt, Table Scans zu erzeugen, ist bekannt. Dass eine LIKE-Suche ebenfalls zu Fullscans neigt, ist leider auch bekannt.
Ich würde aber zunächst mal schauen, ob Oracle Dir einen Volltext-Index für diese Spalte anbietet und ob damit bessere Ergebnisse erzielt werden als mit einer LIKE-Suche auf ein Septett. Dass Du alle möglichen Septette durchgehen musst, wird sich nicht vermeiden lassen, aber ein Volltext-Index ist für eine Suche mitten im Text optimiert.
Wenn das nichts bringt, könntest Du eine Hilfstabelle anlegen. In die stellst Du für je Row der Haupttabelle eine Zeile für jedes mögliche Septett der dbspalte ein und ordnest ihm die ID dieser Zeile zu (wenn's denn eine gibt). Wenn der Key der Haupttabelle umfangreich ist, ist das natürlich umständlich, aber ich bin sicher, Du hast eine Idee, wie Du effizient aus einem Treffer in der Hilfstabelle die passende Row in der Haupttabelle findest.
Die Hilfstabelle kannst du dann mit einem Primärindex auf die Septette versehen und dann ist es für jedes mögliche Septett aus der Eingabe nur noch ein Index Seek und kein Full Table Scan mehr.
Auf die Haupttabelle legst Du dann Trigger, der nach jedem INSERT die nötigen Septette in die Hilfstabelle schreibt, bei jedem DELETE die obsoleten Septette entfernt und bei jedem UPDATE schaut, ob sich die Suchspalte geändert hat und im Ja-Fall die Septette erneuert. Das dürfte einer Stored Procedure bedürfen. Mit T-SQL wüsste ich, wie das geht, Oracle hat dafür seine eigene Syntax und Prozedursprache.
Die Alternative zum Online-Update durch Trigger wäre ein nächtlicher Batchlauf, der die Hilfstabelle neu aufbaut.
Möglicherweise kann man auch geschickter vorgehen und nicht alle Septette einbauen, aber dafür müsste ich mir erstmal länger Gedanken machen. Ich denke da an das Speichern von Triplets, die an strategischen Positionen in der dbspalte stehen. Das könnte die Hilfstabelle verkleinern - aber es wird die Suche nicht beschleunigen.
Wie gesagt: ein "Volltext-Index" Feature sollte die beste Lösung darstellen.
Rolf
Hi,
das ist auf jeden Fall ein Full Table Scan. Dass ein OR generell dazu neigt, Table Scans zu erzeugen, ist bekannt. Dass eine LIKE-Suche ebenfalls zu Fullscans neigt, ist leider auch bekannt.
Danke für Deine Gedanken zum Thema. Leider kann ich dort keine zusätzlichen Indizes oder Tabellen anlegen. Trigger schon gar nicht.
Inhaltlich ist die gewünschte Suche aus meiner Sicht ohnehin unsinnig - insofern werde ich das Thema wohl wegdiskutieren oder das zumindest versuchen - zerlegt die Performance auf einer der wichtigsten Tabellen …
Wie gesagt: ein "Volltext-Index" Feature sollte die beste Lösung darstellen.
die zweitbeste - die beste ist, dieses "Feature" nicht zu implementieren.
cu,
Andreas a/k/a MudGuard
Hallo Andreas,
Leider kann ich dort keine zusätzlichen Indizes oder Tabellen anlegen. Trigger schon gar nicht.
Sowas gilt doch eigentlich nur dann, wenn man auf Fremd-Datenbanken rumturnt oder bei Billig-Hostern. Wenn man beim professionellen Kunden ist, sollte das anders sein.
Aber unprofessionelle technische Rahmenbedingungen dieser Art wären für mich dann ein prima Argument, um die Anforderung zu verweigern. Wenn sie das nicht glauben wollen, dann bau ihnen eine grottenlahme Lösung, die die DB ausbremst, und wenn einer motzt, dann zieh dein CYA-Dokument aus der Tasche, in dem Du das angekündigt hast.
Andererseits lohnt es vielleicht, einen Schritt rückwärts zu gehen und sich den fachlichen Kontext anzuschauen. Ist diese Seven-of-Fourty Anforderung vielleicht ein Y-Problem, und das eigentliche X-Problem lässt sich mit etwas Expertise viel eleganter lösen?
Rolf
Hi,
so, das Thema hat sich erledigt, ich konnte es wegdiskutieren - hab ein paar geeignete Fälle rausgesucht, die zu unerwünschter Zuordnung von Daten zu Kunden geführt hätten (Kunde 1 hätte dann Daten von Kunde 2 gesehen).
Datenschutz und Dauer der Abfrage (> 30s) hat dann doch überzeugt, daß das Unterfangen zu gefährlich ist.
(der von Rolf vorgeschlagene Fulltext-Index wäre, wenn ich das richtig gesehen habe, in der vorhandenen DB-Version nicht verfügbar gewesen)
Auch wenn jetzt keine Lösung mehr gebraucht wird, weil das Problem verschwunden ist, natürlich ein dickes Danke an Rolf für die Gedanken zum Thema!
cu,
Andreas a/k/a MudGuard
Hallo MudGuard,
das ist doch immer am besten, wenn man dem Fachbereich beweisen kann, dass ihre Idee Müll ist.
Rolf
Hi,
das ist doch immer am besten, wenn man dem Fachbereich beweisen kann, dass ihre Idee Müll ist.
Noch besser wäre m.E., wenn die das selber erkennen würden.
cu,
Andreas a/k/a MudGuard