Kako se ne dela z sqli!

Recimo da imamo dve tabeli. Trgovino in avtomobile. In v tabeli avtomobil imamo polje trgovine, kjer imamo z vejico ločene šifre trgovin, kjer se ta avto prodaja.

Primer:

trgovina
trgovina_id – naziv
T1 – Trgovina 1
T2 – Trgovina 2
T3 – Trgovina 3
T4 – Trgovina 4

avto
avto_id – naziv – trgovine
A1 – BMW 5 – T1,T2
A2 – BMW 3 – T1,T3
A3 – Mercedes A – T1,T3,T4
A4 – Mercedes E – T4
A5 – Renault 4 GTL – T1,T2,T3

Kako z enim querijem potegnemo vse trgovine, ki prodajajo recimo A3?

SELECT t1.* FROM trgovina t1 inner join avto t2 on (concat(“,”,t2.trgovine,”,”) like concat(“%,”,t1.trgovina_id,”,%”)) where t2.avto_id=”A3″

Težko bi našel vse kar je narobe s takšnim pristopom.

Začnemo lahko kar pri sami strukturi, ki nikakor ni normalizirana, pa tudi denormalizirana ni z namenom, da bi kaj profitirali, recimo kaj hitreje našli, ampak je enostavno ….. uporabniška? Začetniška? Pesniška? Abnormalna? Hiperkreativna?

Nadalje je uporaba funkcij v join pogoju vredna direktne brce. S tem namreč (lahko) odpade vsakršna optimizacija preko indeksov.

Potem pa še obratna uporaba LIKE operatorja. Namesto da bi se spraševali [polje] LIKE “nek konstanten string”, kjer se še nekako da optimizirati, če je recimo % na koncu, ali z uporabo bolj zahtevnih indeksov, ampak če imamo pa konstanta LIKE [polje], nam pa full scan ne uide.

Ampak, kot rad pravi Dejan Sarka, sej ni važno, če nekaj dela počasi. Računalniki so vsak dan hitrejši. No, v bistvu ima prav. Če imate tak query, v tabelah pa par 10 zapisov, se verjento res ne splača ubadati z optimizacijo. Včeraj pa sem v realnem primeru srečal query, zelo simpl, kjer se je indeks pri 200K zapisih, že krepko poznal. Razlika še ni bila takšna, da bi server zaradi tega bil preobremenjen in odletel, daleč pa tudi ni bilo.