Mailinglisten-Archive |
Adi Sieker wrote: > select ...... where > beschreibung like "%Autos%" > and > beschreibung like "%LKWS%" > > oder, gibt noch eine elegantere lösung?? Jede andere Lösung, bei der die Datenbank Indices benutzen kann, wäre eleganter. Bei der hier vorgestellten Lösung wird eine LIKE- Anweisung mit einem Wildcard am Anfang des Suchbegriffes verwendet. Wie man sich leicht überlegen kann, kann bei einer solchen Query ein Index nicht verwendet werden. Wenn man es sich nicht überlegen kann, findet man den entsprechenden Hinweis im Handbuch seiner Datenbank oder indem man es ausprobiert: mysql> desc applications; +--------------+-----------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+-----------------+------+-----+---------+----------------+ | appnr | int(11) | | PRI | 0 | auto_increment | ... +--------------+-----------------+------+-----+---------+----------------+ mysql> explain select * from applications where appnr like "%1%"; +--------------+------+---------------+------+---------+------+------+------------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +--------------+------+---------------+------+---------+------+------+------------+ | applications | ALL | NULL | NULL | NULL | NULL | 38 | where used | +--------------+------+---------------+------+---------+------+------+------------+ 1 row in set (0.01 sec) mysql> explain select * from applications where appnr like "1%"; +--------------+------+---------------+------+---------+------+------+------------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +--------------+------+---------------+------+---------+------+------+------------+ | applications | ALL | PRIMARY | NULL | NULL | NULL | 38 | where used | +--------------+------+---------------+------+---------+------+------+------------+ 1 row in set (0.00 sec) Wie man sieht, wird in der 2. Query die Verwendung des Keys ermöglicht, in der 1. Query jedoch wegen des führenden Wildcard nicht. Die Query wird genau dann effizient, wenn man eine Tabelle Produkte normalisiert, indem man eine Tabelle Suchbegriffe erzeugt, sodaß eine 1:n Beziehung zwischen Produkten und Suchbegriffen entsteht. create table suchbegriffe ( such_id integer not null primary key auto_increment, produkt_id integer not null, suchbegriff varchar(80) not null, index (produkt_id), index(suchbegriff) ); Nun kann man select * from produkte as p, suchbegriffe as s where p.produkt_id = s.produkt.id and ( s.suchbegriff = "a" or s.suchbegriff = "b" ); abfahren. Auf p.produkt_id ist ein Index, weil es sich um einen PK handelt. Der zugehörige FK s.produkt_id ist ebenfalls indiziert worden. Um die Suche zu beschleunigen, ist s.suchbegriff indiziert und wird ohne führende Wildcards verwendet. Ohne nachlaufende Wildcards kann sogar eine eqref ("=") statt eines Patternmatches verwendet werden, was die Sache noch schneller macht. Dies ist relational korrekt und schneller als Deine Anfrage, also ist es wohl "eleganter". Kristian -- Kristian Köhntopp, NetUSE Kommunikationstechnologie GmbH Siemenswall, D-24107 Kiel, Germany, +49 431 386 436 00 Using PHP3? See our web development library at http://phplib.netuse.de/ (We have moved! Update your bookmarks!)
php::bar PHP Wiki - Listenarchive