U zadnje vreme dosta se bavimo pretragom i to sa dobrim rezultatima. Vrednim radom smo uspešno ubrzali pretragu, a uz vašu pomoć smo pronašli i ispravili i neke sitne propuste u radu. Zato, ovog puta, želim da podelim sa vama malo više tehničkih detalja o tome kako mi to radimo – a sve u cilju širenja znanja. Mi odavno pričamo da za pretragu koristimo Sphinx Search&Indexing server. Na Limundo blogu je bar jednom pisano o njemu, ali na dosta višem nivou, pa sam hteo da dam kratak tehnički tutorial, šta je sphinx i kako ga podesiti, bar iz ugla sistem administratora.
Zamislite da u MySQL bazi podataka držite predmete za prodaju, baš kao na Kupindu. Neki pojednostavljeni model tabele bi izgledao ovako:
CREATE TABLE `MojaBaza`.`Predmeti` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`Naziv` VARCHAR(255) NOT NULL ,
`Cena` DECIMAL(11,2) NOT NULL ,
PRIMARY KEY (`ID`) ,
UNIQUE INDEX `ID_UNIQUE` (`ID` ASC) );
Kada bi iz te tabele hteli da izvučete sve predmete čiji naziv sadrži reč iphone i koji koštaju manje od 30,000 dinara pokrenuli bi ovakav upit:
SELECT * FROM MojaBaza.Predmeti WHERE Naziv LIKE “%iphone%” AND CENA < 30000 ;
Ovakav upit deluje jednostavno, školski je primer rada sa bazom i izvršava se fino na bazi sa 100 predmeta. Ali, daleko pre nego što vaš sistem priđe i blizu onome gde je Kupindo sa svojih 700,000 predmeta ovaj upit će trajati sve duže i duže. Na Kupindu bi mogao da traje i minutima, bez obzira na to kakav je server u pitanju – jednostavno relacione baze nisu vešte u pretraživanju tekstualnih polja, a posebno ne da u njima traže približna poklapanja. Sa druge strane, ovako organizovana baza će čak i sa milion predmeta moći da za manje od 0.1s vrati rezultat upita
SELECT * FROM MojaBaza.Predmeti WHERE ID = 21374;
Ovde na scenu stupa sphinx. Njegova primena je upravo u tome da omogući laku i jednostavnu pretragu podataka, primajući kao deo upita tekst koji se traži, zajedno sa dodatnim uslovima pretrage, a vraćajući kao rezultat ID-eve iz baze, koje posle možete brzo i lako učitati. Na CentOS sam Sphinx možete lako dodati kroz zvaničan download , pa vam ostaje samo podešavanje jednog konfiguracionog fajla u /etc/sphinx/sphinx.conf . Ovaj fajl ima dve sekcije koje treba podesiti – definiciju podataka i definiciju indexa. Definicija podataka za gore dat primer bi izgledala ovako:
source predmeti {
type = mysql
sql_host = moj.db.server
sql_user = neki_username
sql_pass = neki_password
sql_db = MojaBaza
sql_query = SELECT ID, Naziv, Cena FROM Predmeti
sql_attr_uint = Cena
}
Ono što je bitno je da je prvo polje koje upit vraća neki ID – i to je ono što će sphinx vratiti kao rezultat. Dodatno, polje Cena smo definisali kao atribut, pa programer koji radi upit može postavljati dodatni numerički uslov vezan za ovaj atribut – tipa “da je manje od 30,000”. Drugi deo konfiguracije je definicija samog indexa. Za ovaj primer ona bi izgledala ovako:
index Predmet
{
source = predmeti
path = /var/lib/sphinx/test1
docinfo = extern
charset_type = sbcs
min_prefix_len = 0
min_infix_len = 3
enable_star = 1
}
Bitan deo je ovaj vezan za prefix / infix i enable star. Ovde smo, konkretno, rekli spihnx-u da želimo da naši upiti mogu da sadrže džoker karakter i da želimo da vidimo sve kombinacije minimalne dužine 3 karaktera. Sam sphinx će zbog ovoga unapred generisati sve moguće kombinacije i držati ih u svom indexu, što će mu omogućiti da rezultat upita vrati za manje od sekunde, za razliku od desetina minuta koje može biti potrebno relacionoj bazi.
Ubrzanje može bukvalno biti nekoliko redova veličine i zato sam i želeo da pokažem da je korišćenje i konfigurisanje sphinx servera jednostavno. Ako vaš sajt ima potrebe za pretragom tekstualnih podataka iz baze, obavezno dodajte Search&Indexing server – nije teško a i te kako se isplati.