Az internet és a digitális adatok exponenciális növekedésével a hatékony keresés képessége kulcsfontosságúvá vált minden alkalmazás számára, legyen szó e-kereskedelemről, tartalomkezelő rendszerekről vagy akár belső vállalati adatbázisokról. A felhasználók gyors, releváns találatokat várnak el, és ezt a hagyományos adatbázis-lekérdezési módszerek, mint például a LIKE %kulcsszó%
, gyakran nem tudják biztosítani.
Itt jön a képbe a teljes szöveges keresés (full-text search), amely sokkal kifinomultabb és teljesítmény-orientált megoldást kínál. A MySQL, a világ egyik legnépszerűbb nyílt forráskódú adatbázis-kezelő rendszere, beépített támogatással rendelkezik a teljes szöveges kereséshez, amely jelentősen felgyorsíthatja és pontosíthatja a keresési funkciókat. Ez a cikk egy átfogó útmutatót nyújt arról, hogyan implementálhatja és használhatja ki a MySQL teljes szöveges keresésének erejét.
Miért nem elég a hagyományos LIKE operátor?
A legtöbb fejlesztő számára az első gondolat egy keresőfunkció implementálásakor a LIKE
operátor használata SQL lekérdezésekben, gyakran joker karakterekkel (%
) kiegészítve. Például: SELECT * FROM termekek WHERE leiras LIKE '%okosóra%'
. Bár ez működik, számos súlyos korláttal rendelkezik:
- Teljesítmény: Nagy adatbázisok esetén, ahol több ezer vagy millió sor található, a
LIKE '%kulcsszó%'
lekérdezések hihetetlenül lassúak lehetnek, mivel az adatbázis-rendszernek minden egyes sort át kell vizsgálnia (full table scan) a találatokért. Ez egy indexelt oszlopon sem segít, ha a joker karakter az elején van. - Relevancia: A
LIKE
nem tudja rangsorolni a találatokat. Egy dokumentum, amelyben a kulcsszó egyszer fordul elő, és egy másik, ahol százszor, ugyanolyan súlyú találatnak számít. A felhasználók azonban relevancia szerint rendezett találatokat várnak. - Rugalmatlanság: Nem támogatja a természetes nyelvi feldolgozást. Nincs beépített funkció a stop szavak (pl. „a”, „az”, „egy”) figyelmen kívül hagyására, a szótövesítésre (stemming), azaz a szavak gyökerének azonosítására (pl. „futó” és „futás” ugyanarra a gyökérre mutat), vagy a szinonimák kezelésére.
- Pontatlanság: Nem tudja kezelni az elgépeléseket vagy a hasonló kifejezéseket.
Ezek a korlátozások arra ösztönöznek bennünket, hogy egy fejlettebb megoldást keressünk, és ez a MySQL teljes szöveges keresés.
A MySQL teljes szöveges keresés alapjai
A MySQL teljes szöveges keresési funkciója az FULLTEXT
indexekre támaszkodik. Ezeket az indexeket speciálisan úgy tervezték, hogy gyorsan és hatékonyan kereshessenek nagy mennyiségű szöveges adatban. A MySQL 5.6-tól kezdve az InnoDB tárolómotor is támogatja a FULLTEXT
indexeket, ami hatalmas előrelépést jelent, hiszen korábban csak a MyISAM támogatta ezt a funkciót.
FULLTEXT index létrehozása
Egy FULLTEXT
indexet oszlopok egy csoportján hozhatunk létre, amelyekben keresni szeretnénk. Az indexet létrehozhatjuk a tábla létrehozásakor, vagy később is hozzáadhatjuk egy meglévő táblához. Fontos megjegyezni, hogy csak CHAR
, VARCHAR
és TEXT
típusú oszlopokon hozható létre FULLTEXT
index.
-- FULLTEXT index létrehozása tábla létrehozásakor
CREATE TABLE cikkek (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
cim VARCHAR(255) NOT NULL,
szoveg TEXT NOT NULL,
FULLTEXT (cim, szoveg)
) ENGINE=InnoDB;
-- FULLTEXT index hozzáadása meglévő táblához
ALTER TABLE cikkek ADD FULLTEXT (cim, szoveg);
Miután létrehoztuk az indexet, a MySQL felépít egy speciális struktúrát, amely lehetővé teszi a gyors keresést. Ez a folyamat némi időt vehet igénybe nagy táblák esetén.
Keresés a MATCH…AGAINST segítségével
A teljes szöveges keresést a MATCH...AGAINST
szintaxissal végezzük. Ez az operátor két részből áll:
MATCH(oszlop1, oszlop2, ...)
: Itt adjuk meg azokat az oszlopokat, amelyekben aFULLTEXT
indexet létrehoztuk és keresni szeretnénk.AGAINST('keresési_kifejezés' [keresési_mód])
: Itt adjuk meg a keresési kifejezést és opcionálisan a keresés módját.
A keresési módok meghatározzák, hogy a MySQL hogyan értelmezze a keresési kifejezést. Három fő mód létezik:
1. Természetes nyelvi mód (IN NATURAL LANGUAGE MODE)
Ez az alapértelmezett mód, ha nem adunk meg mást. Úgy működik, mint egy tipikus webes keresőmotor: a kulcsszavak relevanciája alapján rangsorolja a találatokat, figyelembe véve a szavak gyakoriságát és elhelyezkedését. Figyelmen kívül hagyja a stop szavakat és a minimális szóhossz alatti kifejezéseket.
SELECT id, cim, szoveg,
MATCH(cim, szoveg) AGAINST('adatbázis MySQL' IN NATURAL LANGUAGE MODE) AS relevancia
FROM cikkek
WHERE MATCH(cim, szoveg) AGAINST('adatbázis MySQL' IN NATURAL LANGUAGE MODE) > 0
ORDER BY relevancia DESC;
A relevancia
oszlop egy numerikus értéket ad vissza, amely a találat fontosságát mutatja. Minél nagyobb az érték, annál relevánsabb a találat. A WHERE
feltétel (> 0
) kiszűri azokat a sorokat, ahol nincs releváns találat.
2. Boole-i mód (IN BOOLEAN MODE)
A IN BOOLEAN MODE
sokkal pontosabb vezérlést biztosít a keresési logikán. Különböző operátorokat használhatunk a keresési kifejezésben, hogy finomítsuk a találatokat. Ez a mód nem rendeli hozzá automatikusan a relevanciát, de továbbra is kiszámolja azt, amit szükség esetén lekérdezhetünk.
A leggyakoribb operátorok:
+
: A szónak kötelezően meg kell jelennie a találatban. (PL:+apple +alma
)-
: A szónak nem szabad megjelennie a találatban. (PL:+telefon -samsung
)>
és<
: A szavak relevanciáját befolyásolja, az egyik fontosabb, mint a másik. (PL:>apple
) *
: Helyettesítő karakter (wildcard) a szavak végén. (PL:alma*
– megtalálja az "alma", "almás", "almasav" szavakat)"szócsoport"
: Pontos kifejezés keresése. (PL:"piros alma"
)~
: Negatív súlyozás, a szó megjelenése csökkenti a relevanciát. (PL:+apple ~pear
)
-- Boole-i keresés: "apple" és "juice" szavakat tartalmazza, de nem tartalmazza a "cider" szót
SELECT id, cim, szoveg,
MATCH(cim, szoveg) AGAINST('+apple +juice -cider' IN BOOLEAN MODE) AS relevancia
FROM cikkek
WHERE MATCH(cim, szoveg) AGAINST('+apple +juice -cider' IN BOOLEAN MODE) > 0;
-- Pontos kifejezés keresése
SELECT id, cim, szoveg
FROM cikkek
WHERE MATCH(cim, szoveg) AGAINST('"gyors processzor"' IN BOOLEAN MODE);
A Boole-i mód különösen hasznos, ha a felhasználó részletesebb és kontrolláltabb keresést szeretne végrehajtani, például egy termékkatalógusban, ahol bizonyos paramétereket kizárni vagy kötelezővé tenni kell.
3. Lekérdezés kiterjesztéses mód (WITH QUERY EXPANSION)
Ez a mód a természetes nyelvi keresést egészíti ki. Akkor hasznos, ha a kezdeti keresési kifejezés túl rövid, vagy ha a felhasználó kevésbé pontosan tudja, mit keres. A MySQL először elvégzi a természetes nyelvi keresést, majd a talált legrelevánsabb dokumentumokból kinyer további kulcsszavakat, és ezeket felhasználva futtatja le a keresést újra. Ez növelheti a találatok számát (recall), de néha csökkentheti a pontosságot (precision).
SELECT id, cim, szoveg,
MATCH(cim, szoveg) AGAINST('autó' WITH QUERY EXPANSION) AS relevancia
FROM cikkek
WHERE MATCH(cim, szoveg) AGAINST('autó' WITH QUERY EXPANSION) > 0
ORDER BY relevancia DESC;
Konfiguráció és testreszabás
A MySQL teljes szöveges keresés viselkedése több szerverváltozóval is testreszabható:
ft_min_word_len
: Ez a változó határozza meg a minimális szóhosszt, amelyet aFULLTEXT
indexelés figyelembe vesz. Az alapértelmezett érték 4. Ha ennél rövidebb szavakra is szeretnénk keresni (pl. "CD", "MP3"), ezt az értéket csökkenteni kell (pl. 2-re). Figyelem: A változtatás után újra kell építeni aFULLTEXT
indexeket azALTER TABLE tablanev DROP INDEX indexnev; ALTER TABLE tablanev ADD FULLTEXT (oszlopok);
parancsokkal.ft_max_word_len
: A maximális szóhossz, az alapértelmezett 84.ft_stopword_file
: Egy fájl elérési útja, amely a stop szavak listáját tartalmazza (szavanként egy sorban). Ezek a szavak figyelmen kívül lesznek hagyva a keresés során. Ha üres stringre állítjuk (''
), a MySQL beépített stop szavai sem lesznek használva. Ez hasznos lehet, ha minden szóra keresni akarunk, vagy ha saját, nyelvre szabott stop szólistát szeretnénk használni.innodb_ft_min_token_size
/innodb_ft_max_token_size
: Ezek az InnoDB specifikus változók ugyanazt a célt szolgálják, mint aft_min_word_len
/ft_max_word_len
, de InnoDB táblák esetén alkalmazandók.
Ezeket a változókat a my.cnf
(Linux) vagy my.ini
(Windows) konfigurációs fájlban állíthatjuk be a [mysqld]
szekció alatt, majd újra kell indítani a MySQL szervert.
[mysqld]
ft_min_word_len=2
ft_stopword_file="/usr/local/mysql/share/my_custom_stopwords.txt"
innodb_ft_min_token_size=2
Ezután ne felejtsük el újraépíteni az érintett FULLTEXT
indexeket!
Fejlett szempontok és korlátok
Bár a MySQL teljes szöveges keresése rendkívül hatékony lehet, fontos tisztában lenni a korlátaival és a teljesítményre vonatkozó szempontokkal is.
Teljesítményoptimalizálás
- Index mérete: A
FULLTEXT
indexek jelentős helyet foglalhatnak az adatbázisban, különösen nagy mennyiségű szöveges adat esetén. - Memória: A MySQL hatékonyan használja a memóriát a
FULLTEXT
indexek kezelésére. Győződjön meg róla, hogy elegendő RAM áll rendelkezésre. - Gyorsítótárazás: A lekérdezési gyorsítótár (query cache) hasznos lehet, de komplex
MATCH...AGAINST
lekérdezések esetén korlátozottabb az alkalmazhatósága.
Korlátok
- Nyelvi támogatás: Bár a MySQL teljes szöveges keresése számos nyelvvel működik (alapvető tokenizálás), a fejlettebb nyelvi funkciók, mint például a szótövesítés vagy a szinonimák kezelése, nem mindig elérhetőek vagy konfigurálhatóak egyszerűen más nyelveken, mint az angol.
- Számok és speciális karakterek: Alapértelmezés szerint a
FULLTEXT
indexek nem indexelik a számokat vagy a speciális karaktereket. Ha számokat is keresni szeretne, azoknak szöveges formában kell lenniük az indexelt oszlopban. - Skálázhatóság: Nagyon nagy forgalmú vagy extrém méretű adatbázisok esetén (terabyte-os nagyságrend) a MySQL beépített teljes szöveges keresése elérheti a korlátait. Ilyen esetekben érdemes külső megoldásokra gondolni.
- Szinonimák: A MySQL nem támogatja beépítetten a szinonimákat. Ha a felhasználó "autó"-t keres, de "gépjármű"-vet tartalmazó dokumentumokat is látni szeretne, ezt manuálisan kell kezelni a lekérdezésben vagy az alkalmazás szintjén.
Alternatív megoldások
Amennyiben a MySQL beépített funkciói már nem elegendőek az Ön igényeinek, érdemes megfontolni dedikált keresőmotorok használatát:
- Elasticsearch / Solr: Ezek rendkívül skálázható, nagy teljesítményű, Lucene alapú keresőmotorok, amelyek számos fejlett funkciót kínálnak (pl. facets, geospatial search, advanced stemming, synonym handling).
- Sphinx: Egy másik népszerű, gyors és hatékony nyílt forráskódú keresőmotor, amely jól integrálható a MySQL-lel.
Ezek a megoldások azonban további komplexitást jelentenek (külön szerverek, adat szinkronizálás), de extrém igények esetén elengedhetetlenek lehetnek.
Gyakorlati implementáció és tippek
Vegyünk egy egyszerű példát egy blogbejegyzés táblán keresztül:
-- Tábla létrehozása FULLTEXT indexszel
CREATE TABLE blog_posts (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
author VARCHAR(100),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FULLTEXT (title, content)
) ENGINE=InnoDB;
-- Minta adatok beszúrása
INSERT INTO blog_posts (title, content, author) VALUES
('A MySQL teljes szöveges keresés alapjai', 'Ez a cikk a MySQL full-text search funkciójának bemutatásáról szól, különös tekintettel az InnoDB motorra.', 'Anna'),
('Optimalizálás MySQL adatbázisokhoz', 'Tippek és trükkök az SQL lekérdezések és indexek optimalizálásához.', 'Bence'),
('Webfejlesztés PHP és MySQL segítségével', 'Útmutató a modern webes alkalmazások fejlesztéséhez.', 'Csaba'),
('Full-text keresés: Problémák és megoldások', 'Áttekintés a teljes szöveges keresés kihívásairól és hatékony implementációjáról.', 'Dóra');
Most futtassunk néhány keresést:
-- Természetes nyelvi keresés: keresés az "MySQL optimalizálás" kifejezésre
SELECT id, title, content,
MATCH(title, content) AGAINST('MySQL optimalizálás' IN NATURAL LANGUAGE MODE) AS relevance
FROM blog_posts
WHERE MATCH(title, content) AGAINST('MySQL optimalizálás' IN NATURAL LANGUAGE MODE) > 0
ORDER BY relevance DESC;
-- Boole-i keresés: "keresés" szót tartalmazza, de nem a "problémák" szót
SELECT id, title, content
FROM blog_posts
WHERE MATCH(title, content) AGAINST('+keresés -problémák' IN BOOLEAN MODE);
-- Keresés "InnoDB" vagy "PHP" szavakra
SELECT id, title, content
FROM blog_posts
WHERE MATCH(title, content) AGAINST('InnoDB PHP' IN BOOLEAN MODE); -- Alapértelmezett: OR logika, ha nincs operátor
Tippek a gyakorlati használathoz:
- Felhasználói felület: Tervezzen olyan keresőfelületet, amely kihasználja a MySQL FTS képességeit. Például, ha a felhasználó idézőjelek közé tesz egy kifejezést, azzal jelezheti, hogy pontos kifejezésre keres (ekkor Boole-i módot használhat).
- Teljesítménymonitoring: Rendszeresen figyelje a
FULLTEXT
indexek teljesítményét és az adatbázis erőforrás-felhasználását. AEXPLAIN
paranccsal ellenőrizheti, hogy a lekérdezések valóban használják-e az indexet. - Cache: Fontolja meg a találatok gyorsítótárazását az alkalmazás szintjén, ha gyakran ismétlődő, azonos kereséseket végeznek.
- Biztonság: Ne feledje a szokásos SQL injekció elleni védekezési praktikákat, amikor a felhasználói bevitelt illeszti be az
AGAINST
függvénybe (pl. prepared statements).
Összefoglalás
A MySQL teljes szöveges keresési funkciója egy rendkívül erős és gyakran alulértékelt eszköz a fejlesztők kezében. Segítségével hatékony, releváns és gyors keresési képességeket építhetünk be alkalmazásainkba anélkül, hogy külső, komplex keresőmotorokat kellene integrálnunk.
Bár vannak korlátai, és nagy forgalmú, extrém igényű rendszerekhez más megoldások (pl. Elasticsearch) lehetnek jobbak, a legtöbb webes és üzleti alkalmazás számára a MySQL FULLTEXT
indexek és a MATCH...AGAINST
szintaxis kiválóan alkalmas a feladatra. A megfelelő konfigurációval és a keresési módok okos kihasználásával jelentősen javíthatja felhasználói élményt és az adatokhoz való hozzáférés sebességét.
Ne habozzon, kísérletezzen a különböző módokkal és konfigurációs beállításokkal, hogy megtalálja az Ön projektjéhez leginkább illő megoldást. A teljes szöveges keresés elsajátítása kulcsfontosságú lépés a modern adatvezérelt alkalmazások építésében!
Leave a Reply