zu schnelles LIKE "%und%"

zu schnelles LIKE "%und%"

am 22.04.2008 09:06:44 von Frank Arthur

Meine Abfrage mit LIKE "%und%" ist irgendwie zu schnell.
Woran kann das liegen, ich bin da irgendwie skeptisch, weil ja bei "%und"
im Gegensatz zu "und" und "und%" kein Index benutzt werden kann.
Und, nein, die Queries waren zum ersten Mal ausgeführt, sie wurden mir
nicht aus dem Cache geliefert.
Es kann doch nicht stimmen, dass MySQL 281.409 Einträge in 0.25 Sekunden
nach einem "und" durchsuchen kann. (Oder doch?)
MySQL 4.0.27

+----------------+------------------+------+-----+---------+ ----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+---------+ ----------------+
| keyword_id | int(10) unsigned | | PRI | NULL | auto_increment |
| keyword_name | varchar(255) | | UNI | | |
+----------------+------------------+------+-----+---------+ ----------------+

EXPLAIN SELECT COUNT(*) FROM keywords WHERE keyword_name LIKE "%und%";
+----------+-------+---------------+--------------+--------- +------+--------+--------------------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+----------+-------+---------------+--------------+--------- +------+--------+--------------------------+
| keywords | index | NULL | keyword_name | 255 | NULL | 281409 | Using where; Using index |
+----------+-------+---------------+--------------+--------- +------+--------+--------------------------+
1 row in set (0.00 sec)

SELECT COUNT(*) FROM keywords WHERE keyword_name LIKE "und";
+----------+
| COUNT(*) |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)

SELECT COUNT(*) FROM keywords WHERE keyword_name LIKE "und%";
+----------+
| COUNT(*) |
+----------+
| 48 |
+----------+
1 row in set (0.00 sec)

SELECT COUNT(*) FROM keywords WHERE keyword_name LIKE "%und%";
+----------+
| COUNT(*) |
+----------+
| 770 |
+----------+
1 row in set (0.29 sec)

SELECT COUNT(*) FROM keywords WHERE keyword_name LIKE "%bei%";
+----------+
| COUNT(*) |
+----------+
| 291 |
+----------+
1 row in set (0.25 sec)

Re: zu schnelles LIKE "%und%"

am 22.04.2008 09:36:35 von Boris Stumm

Frank Arthur wrote:

> Meine Abfrage mit LIKE "%und%" ist irgendwie zu schnell.
> Woran kann das liegen, ich bin da irgendwie skeptisch, weil ja bei "%und"
> im Gegensatz zu "und" und "und%" kein Index benutzt werden kann.
> Und, nein, die Queries waren zum ersten Mal ausgeführt, sie wurden mir
> nicht aus dem Cache geliefert.
> Es kann doch nicht stimmen, dass MySQL 281.409 Einträge in 0.25 Sekunden
> nach einem "und" durchsuchen kann. (Oder doch?)
> MySQL 4.0.27
>
>
+----------------+------------------+------+-----+---------+ ----------------+
> | Field | Type | Null | Key | Default | Extra
>
+----------------+------------------+------+-----+---------+ ----------------+
> | keyword_id | int(10) unsigned | | PRI | NULL |
> | auto_increment |
> | keyword_name | varchar(255) | | UNI | |

Nehmen wir mal an, das keyword_name tatsächlich immer gefüllt ist.
Dann passen auf eine 4kb-Seite im Schnitt max. 16 Tupel, oder insgesamt
68 MB (Ich geh mal von einer Zeichengröße von 8 Bit aus). Selbst eine
schnelle Platte schafft das höchstens in einer Sekunde oder so.

Wahrscheinlicher ist allerdings, das keyword_name im Schnitt viel kürzer
ist (mach mal ein select sum(length(keyword_name)) oder so). Sagen wir
nur 25 Zeichen. Dann müssten nur (grob vereinfacht) 7 MB Daten gelesen
werden. Das ist in 0,1 Sekunden machbar. Substringsuche läuft in O(n),
und das reduziert die Frage auf "Kann man innerhalb von 0,15 Sekunden
einen 7-MB-String durchsuchen. Das scheint mir definitiv möglich zu sein.
Ich hab kurz mal nach "parsing mb/second" gegoogelt und bin auf
http://www.gigalogix.com/products_line.html gestoßen. Die meinen, sie
können 150 MB XML pro Sekunde parsen.

Das war jetzt mal eine sehr vereinfachte Rechnung, aber die Größenordnungen
machen deutlich, das sowas möglich sein sollte.

Re: zu schnelles LIKE "%und%"

am 22.04.2008 09:55:51 von Boris Stumm

Boris Stumm wrote:

> Frank Arthur wrote:
>
>> Meine Abfrage mit LIKE "%und%" ist irgendwie zu schnell.
>> Woran kann das liegen, ich bin da irgendwie skeptisch, weil ja bei "%und"
>> im Gegensatz zu "und" und "und%" kein Index benutzt werden kann.
>> Und, nein, die Queries waren zum ersten Mal ausgeführt, sie wurden mir
>> nicht aus dem Cache geliefert.
>> Es kann doch nicht stimmen, dass MySQL 281.409 Einträge in 0.25
>> Sekunden nach einem "und" durchsuchen kann. (Oder doch?)
>> MySQL 4.0.27
[...]
> Nehmen wir mal an, das keyword_name tatsächlich immer gefüllt ist.
> Dann passen auf eine 4kb-Seite im Schnitt max. 16 Tupel, oder insgesamt
> 68 MB (Ich geh mal von einer Zeichengröße von 8 Bit aus). Selbst eine
> schnelle Platte schafft das höchstens in einer Sekunde oder so.
>
> Wahrscheinlicher ist allerdings, das keyword_name im Schnitt viel kürzer
> ist (mach mal ein select sum(length(keyword_name)) oder so). Sagen wir
> nur 25 Zeichen. Dann müssten nur (grob vereinfacht) 7 MB Daten gelesen
> werden. Das ist in 0,1 Sekunden machbar. Substringsuche läuft in O(n),
> und das reduziert die Frage auf "Kann man innerhalb von 0,15 Sekunden
> einen 7-MB-String durchsuchen. Das scheint mir definitiv möglich zu sein.
> Ich hab kurz mal nach "parsing mb/second" gegoogelt und bin auf
> http://www.gigalogix.com/products_line.html gestoßen. Die meinen, sie
> können 150 MB XML pro Sekunde parsen.
>
> Das war jetzt mal eine sehr vereinfachte Rechnung, aber die
> Größenordnungen machen deutlich, das sowas möglich sein sollte.

Auf ein Wichtiges Detail machte mich eben mein Kollege aufmerksam:
Vermutlich waren die meisten Daten sowieso schon im DB-Puffer, was natürlich
die Zeit des Plattenzugriffs eher irrelevant macht. Denn für einen schnellen
Plattenzugriff muss ja die Tabelle unfragmentiert gespeichert sein. Und im
Hauptspeicher sind die o.g. Geschwindigkeiten unproblematisch.

Re: zu schnelles LIKE "%und%"

am 22.04.2008 10:16:18 von Frank Arthur

> Frank Arthur wrote:
>>> Meine Abfrage mit LIKE "%und%" ist irgendwie zu schnell.

Boris Stumm schrieb:
> Wahrscheinlicher ist allerdings, das keyword_name im Schnitt viel kürzer
> ist (mach mal ein select sum(length(keyword_name)) oder so). Sagen wir
> nur 25 Zeichen. Dann müssten nur (grob vereinfacht) 7 MB Daten gelesen
> werden. Das ist in 0,1 Sekunden machbar. Substringsuche läuft in O(n),
> und das reduziert die Frage auf "Kann man innerhalb von 0,15 Sekunden
> einen 7-MB-String durchsuchen. Das scheint mir definitiv möglich zu
> sein.
>
> Auf ein Wichtiges Detail machte mich eben mein Kollege aufmerksam:
> Vermutlich waren die meisten Daten sowieso schon im DB-Puffer, was
> natürlich die Zeit des Plattenzugriffs eher irrelevant macht. Denn für
> einen schnellen Plattenzugriff muss ja die Tabelle unfragmentiert
> gespeichert sein. Und im Hauptspeicher sind die o.g. Geschwindigkeiten
> unproblematisch.

Ach, ich verstehe. Für die erste Suche muss MySQL die keywords in den
Speicher laden und macht dann die Suche. Für jede weitere Suche werden
die Daten, die bereits im Speicher sind für die Suche benutzt. Klaro, das
ist schneller.

select sum(length(keyword_name)) FROM keywords;
+---------------------------+
| sum(length(keyword_name)) |
+---------------------------+
| 2895686 |
+---------------------------+
1 row in set (0.00 sec)

Knapp 3 MB, also laut deiner Beurteilung relativ wenig. Wohl auch so
wenig, dass es ziemlich lange bei MySQL im Speicher bleibt.

select avg(length(keyword_name)) FROM keywords;
+---------------------------+
| avg(length(keyword_name)) |
+---------------------------+
| 10.2900 |
+---------------------------+
1 row in set (0.31 sec)

Also im Schnitt 10 byte pro keyword.

Vielen Dank für deine Hinweise Boris, das erklärt mir die Geschwindigkeit.