PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Ist SQL schnell genug für mich?


rotalever
2008-02-21, 21:10:12
Habe keine Erfahrung mit SQL-Datenbanken gemacht. Brauche aber für ein Projekt irgendsowas und dachte da an eine sqlite-Datenbank. Bevor ich das lerne, würde ich aber gerne wissen wie ihr folgende Situation einschätzt:
Eine Datenbank mit sagen wir mal 50.000 Datensätzen, jeder davon hat 8 strings. Jetzt geb ich der Datenbank einen String und die soll mir alle Datensätze zurückliefern, wo der String enthalten ist. Geht das in unter 1 Sekunde?

darph
2008-02-21, 21:13:53
1) Ist der String, nachdem du suchst, eine Teilmenge der einzelnen Datenbankfelder? Also suchst du nach "baum" und willst "apfelbaum" finden? Sowas ist eher nicht so schnell. ;(

2) Weißt du, in welcher Spalte du suchst, oder mußt du alle 50k * 8 Felder durchsuchen? Kann dein String irgendwo stehen?

rotalever
2008-02-21, 21:21:03
Ja im schlechtesten Fall kann der String in jeder Spalte stehen und "Apfel" soll auch gefunden werden, wenn im Datensatz "Bratapfelbaum" steht.

huha
2008-02-21, 21:25:49
Ungeachtet der Fragestellung wäre es trotzdem nützlich, ein bißchen grundlegende SQL-Befehle zu lernen, die kann man sowieso immer und für alles brauchen. Geht auch recht schnell.

Zur Performance kommt es auf den Rechner an und auf den RAM. Wenn die Datenbank im RAM gehalten werden kann, geht's eigentlich recht zügig, ist sie zu groß und muß auf die Festplatte, dann wird's ein vergleichsweise langwieriger Spaß.

-huha

rotalever
2008-02-21, 21:30:38
Also wenn ich pro Datensatz 1KB veranschlage, was schon sehr sehr großzügig ist, sind es 50MB, im RAM wäre somit von den Daten allein kein Problem, weiß natürlich nicht, wie viel Verwaltungsaufwand da noch getrieben wird.
Als CPU eine schlechte Consumer CPU als Mindestanforderung, als z.B. mein PC :rolleyes: (XP2200+).

Wenn du sagst, dass es recht schnell ginge, was heißt das? 1sek? oder sind 5sek auch recht schnell? oder eher <<1sek?

Nasenbaer
2008-02-21, 21:50:55
Also ich weiß nicht wie es bei sqlite ist aber für MySQL kann man die eizelnen Spalten auch indizieren wodurch Suchbäume erstellt werden, die einen sehr großen Performanceschub liefern (von mehreren Sekunden auf unter 1 Sekunde).
Hängt natürlich von den zu indizierenden Daten ab aber angenommen, deine Datenbankstruktur ist gut ausgearbeitet, dann sollte deine Wunsch unter einer Sekunden denke ich erreichbar sein mit handelsübliche Hardware. D.h. fü den Fall, dass sqlite und MySQL ähnlich schnell sind.

rotalever
2008-02-21, 21:56:04
Geht das mit dem Suchbaum auch so schnell, wenn ich innerhalb von Strings suche, also den genannten "Apfel" auch im "Bratapfelbaum" finden möchte?

Ja ich weiß den Baum gibt es nicht, aber mir fällt kein besseres Wort ein, wo Apfel in der Mitte vorkommt...

Nasenbaer
2008-02-21, 22:17:53
Geht das mit dem Suchbaum auch so schnell, wenn ich innerhalb von Strings suche, also den genannten "Apfel" auch im "Bratapfelbaum" finden möchte?

Ich hatte damals ein MySQL Projekt, dass aus mehreren hunderttausend Datensätzen ne LIKE Abfrage machen musste (also das Was du willst im Prinzip) und das ging nach der Erstellung der Suchbäume wirklich zügig. Ich glaube ich habe die Datensätze noch und könnte das am Wochenende vielleicht nochmal testen. Das waren Städtenamen also VARCHAR (maximal 256 Zeichen).


Ja ich weiß den Baum gibt es nicht, aber mir fällt kein besseres Wort ein, wo Apfel in der Mitte vorkommt...
Wie wäre es dann mit Granatapfelfrucht? Das gibt es jedenfalls. ^^

Coda
2008-02-21, 22:18:35
Wenn du Substrings suchen willst kannst du keinen Index anlegen, d.h. es wird egal was du benützt scheiße lahm -> O(n) Full Table Scan.

SQL bringt da keinen Vorteil mehr.

Berni
2008-02-21, 23:16:01
Hast du mal ein paar Beispieldatensätze und Suchanfragen?
In MySQL (sqlite weiß ich nicht) gibt es einen Fulltext-Index. Dieser wäre wohl recht gut geeignet und dürfte locker von der Performance her reichen (bei einem Forum mit 250.000 Posts ging eine testweise Suchanfrage gerade in 0.0139s obwohl die Postings vermutlich wesentlich größer sind als deine Wörter)!

Coda
2008-02-21, 23:46:35
Fulltext-Index funktioniert aber nur für getrennte Wörter.

PH4Real
2008-02-22, 00:22:31
http://lucene.apache.org

rotalever
2008-02-22, 10:13:04
Wenn du Substrings suchen willst kannst du keinen Index anlegen, d.h. es wird egal was du benützt scheiße lahm -> O(n) Full Table Scan.
Möglich wäre aber sowas wie Jede Position des 1kb großen Datensatz bekommt einen eigenen Index, sodass dann die Suche auf O(Index(n)*1000) geht, wobei die Konstante je nach Index(n) dann nicht mehr so wichtig ist, wenn es klein genug wäre (Mikrosekundenbereich).

Beispieldatensätze habe ich nicht, aber kann man nicht einfach was zufällig generieren? Spielt doch keine Rolle.


Also ich hab jetzt mal kurz was getestet:
(Python)
from pysqlite2 import dbapi2 as sql
db = sql.connect (":dbmem:")
cur = db.cursor ()
cur.execute ("create table main (a varchar, b varchar, c varchar, d varchar, e varchar, f varchar, g varchar, h varchar);")

import random,string
def rword ():
w = ""
for i in xrange (random.randrange (5,129,1)): w += string.letters[random.randrange(0,26)]
return w

#dauert ne weile..
for i in xrange(50000):
x = cur.execute ("insert into main (a,b,c,d,e,f,g,h) values ('"+rword()+"', '"+rword()+"', '"+rword()+"', '"+rword()+"', '"+rword()+"', '"+rword()+"', '"+rword()+"', '"+rword()+"');")

import time

>>> t = time.time ();cur.execute ("SELECT * from main WHERE a like '%%';") ;x = cur.fetchall (); time.time () -t
<pysqlite2.dbapi2.Cursor object at 0xb78b0b60>
2.7290079593658447

>>> t = time.time ();cur.execute ("SELECT * from main WHERE a like '%a%';") ;x = cur.fetchall (); time.time () -t
<pysqlite2.dbapi2.Cursor object at 0xb78b0b60>
2.5201091766357422

>>> t = time.time ();cur.execute ("SELECT * from main WHERE a like '%hallo%';") ;x = cur.fetchall (); time.time () -t
<pysqlite2.dbapi2.Cursor object at 0xb78b0b60>
0.90533304214477539

>>> t = time.time ();cur.execute ("SELECT * from main WHERE a like '%aaaaaaaaaaaaaaaaaaaaaaaaa%';") ;x = cur.fetchall (); time.time () -t
<pysqlite2.dbapi2.Cursor object at 0xb78b0b60>
0.64097309112548828

Keine Ahnung ob ich das richtig gemacht hab. Ich habe wohl noch nicht einmal einen Index erstellt? Oder macht der das automatisch? Die Zeiten bewegen sich also zwischen 0.64 und 2.7 Sekunden. Wenn man das noch irgendwie optimieren könnte, wäre es ok.

Bietchiebatchie
2008-02-22, 11:01:32
http://lucene.apache.org
Würde ich auch vorschlagen. Lucene ist mittlerweile ziemlich standard und für 50k Einträge ist das eigentlich fast schon overkill - aber dafür gute Performance garantiert.

rotalever
2008-02-22, 11:14:32
Geht das auch mit Python?

Dieses Solr scheint zu gehen. Aber man braucht da noch Java gleichzeitig? Das würde mir gar nicht schmecken.

Ich merke grad, ich hätte sql.connect(":memory:") schreiben müssen. Nur wie kann ich dann vorher gespeicherte Sachen von der Festplatte reinholen?

Bietchiebatchie
2008-02-22, 11:24:20
u.U. hilft dir das: http://pylucene.osafoundation.org/

rotalever
2008-02-22, 11:26:24
u.U. hilft dir das: http://pylucene.osafoundation.org/

Muss da denn ein DB-Server im Hintergrund laufen?

Neomi
2008-02-22, 11:55:28
Ich merke grad, ich hätte sql.connect(":memory:") schreiben müssen. Nur wie kann ich dann vorher gespeicherte Sachen von der Festplatte reinholen?

Die generelle Vorgehensweise ist:

- DB per :memory: erstellen
- DB von Festplatte anhängen (ATTACH-Befehl, siehe SQLite-Doku)
- alles rüberziehen (es gibt da eine Mastertabelle, die dir sagt, was wie zu erstellen ist)
- angehängte DB wieder detachen

Heute Abend kann ich mal nachschauen, wie das genau abläuft, ich habe irgendwo auf meiner Festplatte noch Testcode (C++), der genau das macht.

Berni
2008-02-22, 14:07:44
Beispieldatensätze habe ich nicht, aber kann man nicht einfach was zufällig generieren? Spielt doch keine Rolle.
Sicher spielt es eine Rolle, z.B. wie lange die Wörter sind und was du eigtl. damit genau anstellen willst. Du müsstest doch eigtl. wissen, was in die Datenbank reinkommt?

Ich habs jetzt mal folgendermaßen getestet:
Zuerst der Code zum Befüllen (verwendet paar externe Klassen die ich hier mal weglasse). Es werden Wörter zwischen 5 und 10 Zeichen in 8 Einzelnen Spalten (word1-word8, jeweils Varchar(25)) in eine MySQL-Datenbank eingefügt. Die einzelnen Spalten sind ohne Index. Insgesamt werden 50000 Datensätze eingefügt, die Daten brauchen 3,5MB (Zeilengröße durchschnittlich 73 Bytes).
require('./lib/config.php');
require('./rand_word.class.php');

$run=50; //Anzahl der Gesamtdurchläufe
$reqperrun=10; //Anzahl der Einfügeoperationen pro Durchlauf
$reqpersql=100; //Anzahl der Datensätze, die über eine Abfrage eingefügt werden (Vorsicht wegen Memory Limit)

ini_set('max_execution_time', 0 );
require('./lib/mysql_class.php');
$db=new db($sqlhost,$sqluser,$sqlpassword,$sqldb);
mt_srand((double)microtime()*1000000);

for($i=0; $i<$run; ++$i){
for($j=0;$j<$reqperrun;++$j){
$sql='';
for($k=0; $k<$reqpersql; ++$k){
$word1 = new rand_word(mt_rand(5,10), false, true);
$word2 = new rand_word(mt_rand(5,10), false, true);
$word3 = new rand_word(mt_rand(5,10), false, true);
$word4 = new rand_word(mt_rand(5,10), false, true);
$word5 = new rand_word(mt_rand(5,10), false, true);
$word6 = new rand_word(mt_rand(5,10), false, true);
$word7 = new rand_word(mt_rand(5,10), false, true);
$word8 = new rand_word(mt_rand(5,10), false, true);
$sql .="('".$word1->word."','".$word2->word."','".$word3->word."',
'".$word4->word."','".$word5->word."','".$word6->word."','".$word7->word."','".$word8->word."'),";
}
$db->query('INSERT IGNORE INTO wordtest(word1, word2, word3, word4, word5, word6, word7, word8)
VALUES'.substr($sql, 0, strlen($sql)-1));
}
}
?>
Anschließend habe ich dann mal einfach folgende Abfrage per PHPMyadmin ausgeführt:
SELECT * FROM `wordtest`
WHERE `word1` LIKE '%ari%'
OR `word2` LIKE '%ari%'
OR `word3` LIKE '%ari%'
OR `word4` LIKE '%ari%'
OR `word5` LIKE '%ari%'
OR `word6` LIKE '%ari%'
OR `word7` LIKE '%ari%'
OR `word8` LIKE '%ari%'
LIMIT 0 , 50000
Das Ergebnis:
Zeige Datensätze 0 - 1,429 (1,429 insgesamt, die Abfrage dauerte 0.0550 sek.)
Ich würde also mal einfach so behaupten, dass die Performance der Abfrage an sich absolut unkritisch ist. Ich habe zwar einen Core2Duo E6600 aber so ein gewaltiger Unterschied dürfte da nicht bestehen zumal der Rambedarf ja verschwindend gering ist.
Erhöhe ich die Wortlänge auf 5-129 Zeichen (so wie bei dir) erhöht sich die Zeit auf 0,0830 Sekunden (allerdings überprüfe ich ALLE 8 Spalten während du nur eine machst!), also ebenfalls vollkommen unkritisch.
Was bei dir in deinen Messungen rauskommt ist nicht verwunderlich: Du misst dort nicht die Zeit, die die Abfrage selber benötigt, sondern auch die Zeit, die fürs Holen in das eigentliche Programm nötig ist. Bei deinem ersten Befehl holst du ja alle 50000 Datensätze ab. Bei richtigen Suchabfragen mit vielleicht 100 Ergebnissen dürfte das kein großes Problem sein, bei 50000 Datensätze ist eben doch ein recht hoher Overhead da.
Ich habe mal noch folgenden Testcode benutzt, der eine zufällige 5 Buchstaben lange Suchanfrage stellt:
require('./lib/config.php');
require('./rand_word.class.php');

$i=0;
ini_set('max_execution_time', 0 );
require('./lib/mysql_class.php');
$db=new db($sqlhost,$sqluser,$sqlpassword,$sqldb);
mt_srand((double)microtime()*1000000);

$word = new rand_word(5, false, true);
$sql="SELECT * FROM `wordtest`
WHERE `word1` LIKE '%".$word->word."%'
OR `word2` LIKE '%".$word->word."%'
OR `word3` LIKE '%".$word->word."%'
OR `word4` LIKE '%".$word->word."%'
OR `word5` LIKE '%".$word->word."%'
OR `word6` LIKE '%".$word->word."%'
OR `word7` LIKE '%".$word->word."%'
OR `word8` LIKE '%".$word->word."%'";
$start=microtime(true);
$db->query($sql);
echo 'Dauer: '.(microtime(true)-$start).'<br>';
while($row=$db->fetch_array()){
++$i;
}

echo $i.' Dauer: '.(microtime(true)-$start);
?>
Die erste Zeitausgabe ist noch für die reine Abfrage, die 2. Zeitausgabe beinhaltet das ganze Abholen und in jeweils ein Ergebnisarray zu kopieren. Je nach Anzahl der Suchergebnisse habe ich dann bei mir insgesamt zwischen 0,15s und 0,25s gemessen (Wortlänge 5-129). Das Abholen selbst war allerdings nicht wirklich von entscheidender Bedeutung (0,05s). Wenn ich die Abfrage aber so umändere, dass alle 50000 Datensätze geholt werden, erhöht sich die Gesamtzeit auf 0,63s und die fürs reine Abholen auf etwa 0,3s was dann schon signifikant ist. Gerade deshalb sind das Anwendungsszenario und reale Daten-und Suchabfragen nötig um genaue Aussagen zur Performance treffen zu können.
Zudem scheint mir sqlite und/oder python langsamer zu sein, da der Performanceunterschied normal nicht so ausgeprägt sein sollte.

rotalever
2008-02-22, 15:18:24
Danke, das du dir so viel Mühe gemacht hast.
Ich habe die gefundenen Datensätze direkt gefetched, weil das ja eigentlich dazugehört. Also wenn ich die Datensätze gefunden habe, muss ich ja auch drauf zugreifen können, deshalb hole ich sie mir..
Das mit dem "OR" wusste ich noch nicht wie das geht, weil SQL ja Neuland für mich ist. Deswegen hatte ich zunächst immer nur eine Spalte durchsucht, aber die kostenaufwändigste Operation scheint sowieso das fetchen zu sein.
Ohne fetchen geht es in:
0.000394105911255
0.00020694732666
0.22180891037
0.211771965027
(jeweils meine Beispiele und wieder nur eine Spalte)

Könnte man noch irgendeinen Index erstellen, oder bringt das nichts?

Ich denke mal das fetchen dauert wegen Python so lange.

Berni
2008-02-22, 17:25:23
Ein Index dürfte bzgl. des Fetchen nicht wirklich was bringen denke ich (und hinsichtlich des Suchvorgangs selber ists ja eh relativ schnell), das liegt einfach an der Kommunikation/dem Umkopieren...aber musst du denn wirklich Tausende Datensätze abholen? Evtl. würds ja auch reichen, die Datensätze mit IDs (=Primärschlüssel) zu versehen und nur diese IDs zu holen? Aber solange du nicht verraten willst, was das Ding letztlich machen soll, kann man weitere konkrete Optimierungsmöglichkeiten hier schlecht raten...möglicherweise wärs vielleicht sogar besser, alle 8 Wörter in eine Spalte zu schreiben? Und/Oder man arbeitet zunächst mit indizierten Trigrammen und sucht in den daraus enthaltenen groben Ergebnissen dann weiter?

rotalever
2008-02-22, 17:49:18
Hmm, also die Daten die gesucht werden, die müssen natürlich abgeholt werden, ob der jetzt 1000 findet ist natürlich fraglich, aber wenn jemand so ne Suche in ein Suchfeld eingibt, dann ist ein Live-Effekt ja schon ganz nützlich. Im Endeffekt sollen da Tags von Musikdateien rein, und dann soll man nach irgendwas suchen können, aber es scheint ja eigentlich ganz gut zu funktionieren, wie es jetzt ist.

Da fällt mir ein, das soll ja nur eine der Suchmöglichkeiten sein, die der Benutzer hat, ich hatte das jetzt als Performance-Aspekt genommen, da es die aufwendigste Suche ist. Aber könnte man z.B. Suchen beschleunigen, die ähnlich einer Volltextsuche sind, also wo das Suchwort innerhalb eines Datensatzes direkt vorkommt, z.B.
Datensatz 2135: "...","...","...","...blablabla test test...","...","...","...","..."
und man sucht nach "blablabla" dann müsste der das doch schneller können, also mit Index? Und würde der Index auch bei "blabla" oder "tes" also Anfangsstücken von Wörtern schneller sein?

Gast
2008-02-22, 18:02:41
Ein richtiges DBMS bietet hier Unterstzützung zur Volltextsuche, mit %suchtext% wirst du nichts performantes hinbekommen. Eine richtige Volltextsuche bietet dir dann sogar die Option an, dass dir Treffer in ähnlicher Schreibweise bzw. einer anderen Zeitformen als der eingegebene Suchtext angezeigt werden.

rotalever
2008-02-22, 18:59:15
Ein richtiges DBMS bietet hier Unterstzützung zur Volltextsuche,
Welches braucht denn keinen zusätzlich laufenden Datenbankserver und geht mit Python, sowei ich verstanden hatte braucht dieses Apache Teil das ja. Das ist für eine End-User-Anwendung nicht vernünftig zu gebrauchen.

Coda
2008-02-22, 19:23:47
Ein richtiges DBMS bietet hier Unterstzützung zur Volltextsuche, mit %suchtext% wirst du nichts performantes hinbekommen. Eine richtige Volltextsuche bietet dir dann sogar die Option an, dass dir Treffer in ähnlicher Schreibweise bzw. einer anderen Zeitformen als der eingegebene Suchtext angezeigt werden.
Ich hab's schonmal gesagt: Volltextsuche sucht nur nach getrennten Wörtern. Das funktioniert hier nicht.

Gast
2008-02-22, 19:24:25
Welches braucht denn keinen zusätzlich laufenden Datenbankserver und geht mit Python, sowei ich verstanden hatte braucht dieses Apache Teil das ja. Das ist für eine End-User-Anwendung nicht vernünftig zu gebrauchen.

Hä? Kannst du das mal in ordentlichen Sätzen formulieren? Ist das nun eine Client/Server Anwendung oder was ist jetzt nicht zu gebrauchen?

Gast
2008-02-22, 19:34:24
Ich hab's schonmal gesagt: Volltextsuche sucht nur nach getrennten Wörtern. Das funktioniert hier nicht.

Beschäftige dich erst mal mit dem Thema anstatt hier dumm rumzunüllen. Es gibt Datenbanksysteme, die können einen Volltextindex in einem Katalog extern/außerhalb der DB speichern und ein externes Modul übernimmt dann die Volltextsuche. Das ganz ist dann über herstellerspezifische SQL Erweiterungen angebunden.

Berni
2008-02-22, 19:41:53
MySQL hat grundsätzlich nichts mit dem Apache HTTP-Server zu tun, das vorgeschlagene Lucene auch nicht. Lucene ist aber wohl auch nicht geeignet, denn da heißt es:
Note: You cannot use a * or ? symbol as the first character of a search.

Es wäre vielleicht zu empfehlen mittels LIMIT die Ergebnisse zu begrenzen auf z.B. 100 Ergebnisse, sonst wirds ja auch arg unübersichtlich. Evtl. kann man dann über mehrere Seiten zum Blättern Zugriff auf die weiteren Datensätze geben.

Die Anwendung sowie der Datenbestand soll also beim Endkunden laufen und nicht auf einem Server? Was soll das denn dann für eine Oberfläche sein mit Python? DOS-Box? Wäre da nicht Java mit einer GUI besser geeignet?

Aber könnte man z.B. Suchen beschleunigen, die ähnlich einer Volltextsuche sind, also wo das Suchwort innerhalb eines Datensatzes direkt vorkommt, z.B. ...
Also diese Frage habe ich überhaupt nicht kapiert. Ist das nicht dieselbe Suche??? Es wird ja bei deinem Beispiel wieder nicht nach einem Wortanfang gesucht sondern irgendwas mittendrin. Wenn du die Suche aber so eingrenzen kannst, dass der Suchbegriff am Anfang der Spalte steht, so hilft ein normaler Index, wenn der Suchbegriff der Anfang eines Wortes steht, so hilft ein Fulltext-Index, aber NUR dann, wenn du die Abfrage mit MATCH ... AGAINST machst (und außerdem möglicherweise nur in MySQL und nicht sqlite).

@Gast über mir: Es wird aber wohl ein frei erhältliches DBMS hier benötigt. PostgreSQL bietet irgendwas in der Richtung, kennst du dich damit vielleicht aus? Würde mich wirklich interessieren, ob da mehr geht...

rotalever
2008-02-22, 20:09:28
Es wäre vielleicht zu empfehlen mittels LIMIT die Ergebnisse zu begrenzen auf z.B. 100 Ergebnisse, sonst wirds ja auch arg unübersichtlich. Evtl. kann man dann über mehrere Seiten zum Blättern Zugriff auf die weiteren Datensätze geben.

Ne geht nicht, so alles aufeinmal, bzw. in besonderer Struktur, die ich mir noch überlege angezeigt werden

Die Anwendung sowie der Datenbestand soll also beim Endkunden laufen und nicht auf einem Server? Was soll das denn dann für eine Oberfläche sein mit Python? DOS-Box? Wäre da nicht Java mit einer GUI besser geeignet?

Mit Python kann man auch GUIs machen...

Also diese Frage habe ich überhaupt nicht kapiert. Ist das nicht dieselbe Suche??? Es wird ja bei deinem Beispiel wieder nicht nach einem Wortanfang gesucht sondern irgendwas mittendrin. Wenn du die Suche aber so eingrenzen kannst, dass der Suchbegriff am Anfang der Spalte steht, so hilft ein normaler Index, wenn der Suchbegriff der Anfang eines Wortes steht, so hilft ein Fulltext-Index, aber NUR dann, wenn du die Abfrage mit MATCH ... AGAINST machst (und außerdem möglicherweise nur in MySQL und nicht sqlite).

Ja ich meine der Suchbegriff soll am Anfang stehen in dieser alternativen Suche, du sagst aber er muss am Anfang der Spalte stehen, warum nicht innerhalb eines Satzes (Satz im Sinne von Aneinanderreihung von Wörterb) der Spalte?

@Gast über mir: Es wird aber wohl ein frei erhältliches DBMS hier benötigt.
So sieht es aus, ich habe leider kein Geld für Bibliotheken usw.

rotalever
2008-02-22, 20:14:47
Hä? Kannst du das mal in ordentlichen Sätzen formulieren? Ist das nun eine Client/Server Anwendung oder was ist jetzt nicht zu gebrauchen?
Ich hatte es so verstanden, als sei dieses Apache Teil, was hier im Thread verlinkt wurde ein Datenbanksystem, dass auf dem Client/Server Prinzip aufbaut. Ja ich weiß, es hat nichts mit dem Apache Server selbst zu tun. Aber MySQL ist ja z.B. auch ein Server.

Auf jeden Fall ist das für eine Enduser-Anwendung immer schlecht, weil dann der User immer noch einen Server starten muss, bzw. das ganze installiert werden will, usw. Das bereitet nur Probleme. Weshalb so etwas wie sqlite eigentlich optimal wäre, da es abgeschlossen ist. Die Performance war ja im Endeffekt nach den Benchmarks auch gar nicht mal soo schlecht.


Und jetzt wollte ich halt zusätzlich wissen, ob man andere Suchanfragetypen eben zusätzlich durch einen Index beschleunigen kann, also Suchanfragen, die nicht so allgemein formuliert, wie im Ausgangsposting sind. Der User soll halt wählen können, wie genau er suchen will, also ob die Suchwörter auch in anderen enthalten sein dürfen oder nicht.

Neomi
2008-02-22, 20:18:54
Ich merke grad, ich hätte sql.connect(":memory:") schreiben müssen. Nur wie kann ich dann vorher gespeicherte Sachen von der Festplatte reinholen?

Falls das Problem und der Einsatz von SQLite noch aktuell ist, hier ist die Lösung dafür in C:

int CreateMemoryDB_CopyFromFile(char *pszFileName, sqlite3 **db)
{
sqlite3_stmt *stmt;
char szText[1024];

if (sqlite3_open(":memory:", db) != SQLITE_OK)
{
sprintf_s(szText, "Can't open database: %s", sqlite3_errmsg(*db));
MessageBoxA(NULL, szText, "Error", MB_OK | MB_ICONERROR);

return(SQLITE_ERROR);
}

sprintf_s(szText, "ATTACH '%s' AS sourcedb", pszFileName);
sqlite3_exec(*db, szText, NULL, NULL, NULL);

sqlite3_prepare_v2(*db, "SELECT name, sql FROM sourcedb.sqlite_master WHERE type = 'table'", -1, &stmt, NULL);

while (sqlite3_step(stmt) != SQLITE_DONE)
{
const char *pszTableName = (const char*) sqlite3_column_text(stmt, 0);

sqlite3_exec(*db, (const char*) sqlite3_column_text(stmt, 1), NULL, NULL, NULL);

sprintf_s(szText, "INSERT INTO '%s' SELECT * FROM sourcedb.'%s'", pszTableName, pszTableName);
sqlite3_exec(*db, szText, NULL, NULL, NULL);
}

sqlite3_finalize(stmt);

sqlite3_prepare_v2(*db, "SELECT sql FROM sourcedb.sqlite_master WHERE type = 'index'", -1, &stmt, NULL);

while (sqlite3_step(stmt) != SQLITE_DONE)
sqlite3_exec(*db, (const char*) sqlite3_column_text(stmt, 0), NULL, NULL, NULL);

sqlite3_finalize(stmt);

sqlite3_exec(*db, "DETACH sourcedb", NULL, NULL, NULL);

return(SQLITE_OK);
}

Ist ein etwas älterer Testcode und nicht die Sprache deiner Wahl, der logische Ablauf bleibt aber und läßt sich leicht übernehmen.

Berni
2008-02-22, 20:21:24
Beispiel:
In der Spalte steht "Ich gehe nach Hause". Wenn du nun nach "geh" suchen willst, so hilft ein normaler Index nichts. Wenn du aber einen Fulltext-Index hast, hilft dieser WENN du die spezielle Syntax mit "Match Against" nutzt (=>google!). Allerdings musst du schauen, obs diesen Fulltextindex in sqlite gibt.
Wenn du dagegen nach "Ich" suchst, hilft sowohl ein normaler Index als auch ein Fulltext-Index. Wenn du nach "aus" suchen willst und diesen Datensatz (wegen "Hause") finden willst, hilft keiner der beide Indexarten.

Gast
2008-02-22, 20:22:54
@Gast über mir: Es wird aber wohl ein frei erhältliches DBMS hier benötigt. PostgreSQL bietet irgendwas in der Richtung, kennst du dich damit vielleicht aus? Würde mich wirklich interessieren, ob da mehr geht...

Bei freien/kostenlosen Systemen kann ich leider auch nicht helfen. Ich bin hier etwas MSSQL vorbelastet. Dort wird so ein Volltextsuche Modul schon seit Ewigkeiten mitgeliefert, was aber extra installiert werden muss.
Bei den kostenlosen MSDE/Express Versionen ist das leider nicht dabei.

rotalever
2008-02-22, 20:26:20
Danke euch, ich glaube ich hab jetzt genug Stichwörter mit denen ich weiterschauen kann.

@Neomi: Danke auch für den Quellcode. Ich werde ihn mir jetzt mal anschauen, eine Implementation in Python ist ja dann nicht mehr schwer.

Coda
2008-02-22, 22:47:01
Beschäftige dich erst mal mit dem Thema anstatt hier dumm rumzunüllen. Es gibt Datenbanksysteme, die können einen Volltextindex in einem Katalog extern/außerhalb der DB speichern und ein externes Modul übernimmt dann die Volltextsuche. Das ganz ist dann über herstellerspezifische SQL Erweiterungen angebunden.
Es sucht trotzdem nur nach getrennten Wörtern. Sonst ergibt ein Index keinen Sinn. Und ja, ich habe Volltextsuche schon öfters verwendet.