MSSQL/T-SQL: alternative zu LIKE '%abc%'

Der MySQL Datenbank-Server f√ľr Internet- und Intranet-L√∂sungen.

MSSQL/T-SQL: alternative zu LIKE '%abc%'

Beitragvon max_payne » Di 26 Aug, 2008 18:03

hallo!
ich suche eine alternative zu dem oben genannten Like. grund: performance

ich habe es bereits mit dem volltextindex versucht, allerdings geht das nur wortweise.
dh: bei text "dies ist abc" kann man nach dies, ist, abc suchen, jedoch nicht nach "ab" oder "ies"

kennt jemand eine lösung?
aon (8/0,7) + HUI Flat 20 | http://www.mku.name (<-- Burstcoin Tutorial)
max_payne
Ultimate Power-User
Ultimate Power-User
 
Beiträge: 4978
Registriert: Mo 30 Aug, 2004 12:25

Beitragvon wagsoul » Mi 27 Aug, 2008 07:56

Hast du das schon gelesen?

http://dev.mysql.com/doc/refman/5.1/de/ ... earch.html

Um so einen Volltext-Index wirklich zu nutzen, muss man mit anderen Kriterien als 'like' in der Abfrage suchen.

Kommen in deiner Where-Bedingung noch andere Spalten als die mit dem zu suchenden Text vor, oder machst du vielleicht sogar einen Join? Wenn ja, könnte man da auch noch viel optimieren.

√úber jede Spalte die in der Where-Klausel vorkommt, kannst du einen Index legen, und f√ľr jeden Join einen Index √ľber den Prim√§rschl√ľssel der einen Tabelle und dem Fremdschl√ľssel in der anderen.
wagsoul
Profi-User
Profi-User
 
Beiträge: 1638
Registriert: Fr 04 Mai, 2007 20:53

Beitragvon wagsoul » Mi 27 Aug, 2008 08:42

Oder eine Möglichkeit gibt es wohl doch, die Suche (wahnsinnig) effizient zu machen.

Und zwar, indem man Informationen teilweise redundant speichert.


Ich nehme hier mal an, dass diese "Tabelle1" deine ist, die die Spalte mit dem zu suchenden Text beinhaltet.

Sie sieht spaltenmäßig so aus:
id,
spalte1,
psalte2,
spalte3,
...
textspalte

Die Spalte "textspalte" ist dabei jene, die deinen Text enthält.

Sagen wir, in dieser Tabelle ist folgende Zeile:

1, 4, 6, 3, ...., 'Das ist ein Test-Text'

Nun nehmen wir an, du willst nach allen Zeilen suchen, die in der Spalte textspalte das Wort "ist" enthalten. Dabei wirst du meine obige Zeile (+ andere vorhandene) erhalten.


Das könnte man mit einer zusätzlichen Tabelle realisieren, die so aussieht:
create table suchtabelle
id number(19) primary key,
tabelle1Id references tabelle1(id),
wort varchar2(1024) not null


Mit dieser 2. Tabelle machst du nichts Anderes, als dasss du daf√ľr sorgst, dass s√§mtlicher Text dort auch eingetragen ist - allerdings unterteilt auf 1 Wort pro Tabellenzeile.

In unserem Beispiel w√ľrde f√ľr den oben beschriebenen Eintrag aus Tabelle1 Folgendes in der 2. Tabelle stehen:

1, 1, 'Das'
2, 1, 'ist'
3, 1, 'ein'
4, 1, 'Test-Text'


Willst du nun nach Zeilen der Tabelle1 suchen, die das Wort 'ist' in der Textspalte enthalten, so machst du das so:

select * from Tabelle1 where id in (

select distinct tabelle1Id from suchtabelle where LENGTH(wort) >= LENGTH('ist') and wort like '%ist%'

)

Vielleicht hilft das ja. Falls nicht, k√∂nntest du versuchen den Inhalt der 2. Tabelle so zu √§ndern, dass dieser nicht nur ganze Worte, sondern auch Wortfetzen enth√§lt. Dann kannst du n√§mlich auf das % am Anfang in der Like-Klausel verzichten, womit dann ein Index genutzt wird, denn du dann nat√ľrlich √ľber die Wort-Spalte legen musst.

Ist ein %-Zeichen am Anfang eines like-Arguments, werden nämlich keine Indizes benutzt.
wagsoul
Profi-User
Profi-User
 
Beiträge: 1638
Registriert: Fr 04 Mai, 2007 20:53

Beitragvon wagsoul » Mi 27 Aug, 2008 09:08

Als Endergebnis w√ľrde das dann so aussehen:

create index idx_suchtabelle_wort on suchtabelle(wort);

Wegen des Satzes "Das ist ein Test-Text" w√ľrde das drinnen stehen:

1, 1, 'Das ist ei'
2, 1, 'as ist ein'
3, 1, 's ist ein '
4, 1, ' ist ein T'
5, 1, 'ist ein Te'
6, 1, 'st ein Tes'
7, 1, 't ein Test'
8, 1, ' ein Test-'
9, 1, 'ein Test-T'
10, 1,' in Test-Te'
11, 1,' n Test-Tex'
12, 1,' Test-Text'
13, 1,' est-Text'
14, 1,' st-Text'
15, 1,' t-Text'
16, 1,' -Text'
17, 1,' Text'
18, 1,' ext'

Und der Select wäre so:

select * from Tabelle1 where id in (

select distinct tabelle1Id from suchtabelle where wort like concat(substring('ist', 0, 10), '%')

)

and textspalte like '%ist%';


Hier hat man sodann im Hauptselect erst wieder ein langsames like '%ist%', das ist aber notwendig, da der innere Select nur f√ľr Suchw√∂rter mit max. 10 Zeichen funktioniert, und bei l√§ngeren Suchw√∂rtern eventuell zu viele Ergebnisse liefert.

Andererseits sollte dieser innere Select trotzdem so gut filtern, dass der Rechenaufwand f√ľr das √§u√üere langsame Like gegen "nicht notwendig" gehen sollte.


Auch wenn meine in der vorherigen Antwort pr√§sentierte L√∂sung vielleicht nicht ganz optimal ist, sollte man hiermit das Problem nun wirklich endg√ľltig erschlagen.

Es ist halt eine Frage des Festplattenspeichers, den man f√ľr diese Suchoptimierung bereit ist zu verwenden, und auch wie gut so eine MySQL-Datenbank mit Datenmengen im GB-Bereich umgehen kann, falls sich eine entsprechende Menge ergeben sollte.


--edit:
Wieso ich solche Beitr√§ge hier scheibe, wei√ü ich selber nicht. Woanders w√ľrde man damit gutes Geld verdienen ;-)
wagsoul
Profi-User
Profi-User
 
Beiträge: 1638
Registriert: Fr 04 Mai, 2007 20:53

Beitragvon max_payne » Mi 27 Aug, 2008 20:30

Wieso ich solche Beitr√§ge hier scheibe, wei√ü ich selber nicht. Woanders w√ľrde man damit gutes Geld verdienen

hui, dann sag ich mal danke!

ich werd mir das morgen gleich in der fr√ľh anschaun und umsetzen ;-)
aon (8/0,7) + HUI Flat 20 | http://www.mku.name (<-- Burstcoin Tutorial)
max_payne
Ultimate Power-User
Ultimate Power-User
 
Beiträge: 4978
Registriert: Mo 30 Aug, 2004 12:25


Zur√ľck zu MySQL

Wer ist online?

Mitglieder in diesem Forum: Yahoo [Bot] und 1 Gast