zizi ajánlásával :) kérdezek a T. Egybegyűltektől: hogy lehet MySQL-ben pontosan kezelni az ékezetes betűket? Hogy lehet megoldani, hogy ha a keresésem ... LIKE '%szék%', és a találatok között ott van a "szövőszék" és a "székely", ne legyen ott a "Szekszárd" és a "Mély szekérút" is? Mer' most ott vannak... (művészeti adatbázis)
"Es persze ismet hozzateszem - ebben a topicban nagon halkan - , hogy ezert szeretem en nagyon a PostgreSQL-t, mert ott alapbol van tomb tipusu mezo, es PL/PgSQL-ben csodasan lehet is vele dolgozni. Ott altalaban ezt hasznalom a cimkezesre."
a mostani cimkes kerdesben pont rossz pelda a tomb a pg-be, mert nem igazan erre valo :) Any-vel matcheltetni performancia killer, ha esetleg tudnal GIN index-et hasznalni jo lenne, de nem igazan lehet erre. Se nem int tombod nincs, se nem kulcs,ertek parjaid hstore-hez. Raadasul egy gyakran updatelt tablara nem jo dolog gin indexet rakni.
Szoval jo dolog az teny, de ha olyan kell, hogy mely kepek vannak a leggyakoribb cimkekkel, vagy csak siman melyek a leggyakoribb cimkek, maris nem alkalmas a kerdesre. (szimplan mivel nem arra talaltak ki, hogy a kapcsolotablakat helyettesitse)
Itt pl van egy ottletes felhasznalasa: http://geekblog.over-blog.com/article-24266883.html
"En nem emlekszem arra, hogy kovetelmeny lett volna, hogy egy mezoben csak egy cimke szerepeljen." Nem kell emlékezni, ott van a 1744. hozzászólás 3. bekezdésében.
"A masik, hogy egy adatmodell attol meg nem hibas, hogy egy bizonyos adatra nem indexelheto" Ezzel egyetértek és ilyent nem is írtam (ott egy felsorolás van, ami egy általad nem szeretett 1:N kapcsolatot jelent a lista fölötti mondattal - valami ilyesmi a lista definíciója, de semmiképpen sem az, hogy a 3. pont az 1. következménye). Az adatmodell attól hibás, hogy 1:N (1 kép - bármennyi cimke) kapcsolatot tárolsz 1:1 kapcsolatként (1 kép - 1 valami, ami nem cimke).
"Ugyanis ha az elsodleges szerepe a cimkeknek az, hogy egy tartalomtipus alatt szepen megjelenitsek oket (jellemzoen pl. a flickr ilyen)" Amiről írsz nem cimke, hanem a kép leírása, és az valóban 1:1 kapcsolatban van a képpel, ezért valóban a képek táblában a helye. A cimkék elsődleges szerepe a keresés segítése. Egy elemhez (pl. képhez) jellemzően több cimke is tartozik, ezért 1:n kapcsolatról beszélünk. A korábban használt kategóriákat váltották ki a cimkékkel, ugyanis a kategóriák túl merevek voltak (nem konkrétan a Flickr, úgy általában). Nem sok értelme van a cimkéknek ha nem használják őket keresésre. A Flickr-en is ez a céljuk, és ugye nem gondolod, hogy pl. a budapest lekérdezés table scant csinál több millió soron mert nincs index? Az pedig már abszurdum, hogy közben még soronként csinálna egy nagyon költséges stringműveletet is vagy like-ot. Egy Flickr méretű adatbázisban valószinűleg 3 táblában tárolják a képeket és a cimkéket: képek, cimkék, és képek_cimkéi (kapcsolótábla). Magam ismétlem: ennek az az előnye, hogy egy cimke csak egyszer szerepel a rendszerben, azaz kisebb a cimkék tábla mérete, a kapcsolótábla viszont csak numerikus mezőkből áll, melyek kezelése nagyon olcsó. Lásd még (1). Ugye azt sem gondolod komolyan, hogy minden lekérdezéskor lefut egy split és ez olcsóbb mint a join?
"mert egy ujabb tabla joinolasa a lekerdezesbe tul sok eroforrast pazarol el a hasznossagahoz kepest, foleg ha 10000-es nagysagrend fole emelkedik mondjuk a tartalomelemek vgy a cimkek szama." Tízezres nagyságrendű sor még a Paradoxnak sem okozott gondot, nemhogy a MySQL-nek vagy más mai SQL szervernek. A join költsége kicsi a stringműveletekhez és table scanhez képest, ezt általában ki lehet jelenteni a mai SQL szerverekről - természetesen ha van index a joinban szereplő mezőkön és a join feltétel olyan, hogy az index használható is (ha nem olyan akkor javítani kell az adatmodellen).
"Nem ismerem pontosan a MySQL motorjat ilyen szempontbol, de az szinte biztos, hogy egy barmilyen join az ON feltetel miatt igenyel egy plusz szekvencialis keresest egy tablan." Tudom, hogy a MySQL nem a legjobb SQL szerver, de azért kételkedem abban, hogy nem használja az indexeket. Én bízom benne, hogy csak egy index scan kell a joinhoz, és ez lényegesen olcsóbb, mint a split vagy a like.
"De ezt minden esetben a felhasznalas jellege donti el." Ez így tökéletesen igaz, DE a cimkék jellemzően olyan adatok, melyre keresni szoktak, sőt, a cimkék létezésének egyetlen célja a keresés, mert sokkal könnyebben kezelhetők mint a kategóriák és olcsóbban előállíthatók mint egy full text index.
Az a "cimke" amiben nem keresnek a kép cime vagy leírása (kedvenc példádban, Flickr-ben: Title - a kép címe, Description - a kép leírása, Tags - cimkék, és hidd el, hogy a cimkék nem egy újab mező a képek táblában a Flickr-nél sem). Persze kereshetnének a címben is, de az sokkal költségesebb mint a cimkék használata.
"megintcsak erosen felhasznalasfuggo" Nem. Ha cimkéK (fontos a végén a K betű), akkor több cimke van egy képhez, tehát 1:N. Ha cimke (nincs K betű a végén) akkor egy cimke van egy képhez, tehát 1:1, ezesetben pedig már nem cimke, hanem cím vagy leírás, csak te valamilyen okból másképpen nevezed (ennyi erővel pista is lehetne a neve).
Maradjunk a továbbiakban a cimkék klasszikus értelmezésénél, azaz 1 elemhez több cimke tartozhat (1:N kapcsolat), és a cimkék célja a keresés.
"A vilagon mindenhol van escape-elendo elvalaszto karakter, mar csak a bevitel miatt is. Kulonben egy php-ben vagy akarmi masban megirt parser honnan tudna, hogy egy formbol erkezo "anya, apa, csirke" harmasbol az "anya, apa" egy cimkenek szamit vagy kettonek? Vagyis ezt a problemat semmikepp sem tudod megkerulni." Meg tudnám kerülni, de sajnos már megelőztek: 1 beviteli mező - 1 cimke. A Flickr spórol, náluk egy mezőben lehet felvinni az összes cimkét, de sem elméleti sem gyakorlati akadálya nincs a több mezős bevitelnek. Van éles, nyilvános rendszer is, ahol 1 beviteli mezőben 1 cimkét rögzítesz, pl. Yahoo! Bookmarks.
"de az egyszeru tartalommegjelenites cimkestul meg sokkal egyszerubb es gyorsabb" Az egyszerűbbet nem nagyon tudom értelmezni, mert a megjelenítést nem befolyásolja a tárolás módja. A gyorsabbat pedig bízzuk az adatbázismotorra, én bízom bennük :-)
"normalformara hozod-e a tablat" Nemrég írtam már nem tudom melyik topikban, hogy a normálforma nem cél, hanem eszköz, vagyis ebben egyetértünk.
"Mivel az eredeti kerdes arra vonatkozott, hogy egy cimkezohoz altalaban milyen struktura szukseges" Az egyetlen gond az, hogy te nagyon egyedien értelmezed a cimkézést, azaz nem több cimkének tekinted a képhez tartozó cimkéket, hanem egy szövegnek. (1) A Flickr-en sem szöveg a képhez tartozó cimkék halmaza, hanem N db. cimke, külön sorban megjelenítve, tehát fel sem merül az igény arra, hogy egy mezőben, szövegként legyen tárolva, hiszen egy ilyen tárolásnál nemcsak a keresések, hanem a megjelenítés is lényegesen lassúbb lenne a minden képnél szükséges split miatt.
"en batorkodtam a legegyszerubb megoldasbol kiindulni" Mivel te szövegnek tekinted a cimkék halmazát ezért érzed úgy, hogy egyszerűbb. Ám ha a cimkék halmazát valóban halmaznak tekinted akkor máris split kellene, ami nem biztos egyszerűbb mint az 1:N tárolás.
Olyan "mellékes" dolgokat mint pl. tag cloud vagy "top 10 cimke" meg sem merek említeni. Van tipped hogyan lehetne megcsinálni, ha szövegesen tárolod a cimkéket? Elfogadhatónak találod a megoldást? Mert én nem. Normál esetben "select cimke, count(cimke) as darab from cimkék group by cimke order by darab desc limit 0, 50"?
"PostgreSQL-t, mert ott alapbol van tomb tipusu mezo" Az ilyen egyedi megoldásokkal az a gond, hogy a tudásod és az adataid is hordozhatatlanná válnak egy idő után.
Összefoglalva és részemről lezárva a témát: A cimkéket (akármit) tekintsük cimkének (akárminek) és kezeljük is aképpen, ezáltal lényegesen csökkentjük a jövőbeni módosítások szükségességét.
En nem emlekszem arra, hogy kovetelmeny lett volna, hogy egy mezoben csak egy cimke szerepeljen. Ez az egyik.
A masik, hogy egy adatmodell attol meg nem hibas, hogy egy bizonyos adatra nem indexelheto, ezt minden esetben a felhasznalas mikentje donti el. Ugyanakkor egy egyszeru lekerdezes szempontjabol nagyon nem mindegy, hogy egy adott - es kinyerni akart - adathalmaz hany adattablaban helyezkedik el. Ugyanis ha az elsodleges szerepe a cimkeknek az, hogy egy tartalomtipus alatt szepen megjelenitsek oket (jellemzoen pl. a flickr ilyen), akkor nem kell a cimkeket indexelni, mert egy ujabb tabla joinolasa a lekerdezesbe tul sok eroforrast pazarol el a hasznossagahoz kepest, foleg ha 10000-es nagysagrend fole emelkedik mondjuk a tartalomelemek vgy a cimkek szama. Nem ismerem pontosan a MySQL motorjat ilyen szempontbol, de az szinte biztos, hogy egy barmilyen join az ON feltetel miatt igenyel egy plusz szekvencialis keresest egy tablan.
Ha viszont (pl. YouTube) a cimkeket related tartalom eloallitasara is hasznalja a rendszer, vagy mas miatt gyakoriak a cimke szerinti lekerdezesek, akkor valoban van ertelme a cimkeket indexelni, es ez esetben valoban olyan adatbazissema kell, amiben a cimkek indexelhetok. De ezt minden esetben a felhasznalas jellege donti el.
Az, hogy a cimkezest 1-1 vagy 1-n kapcsolatnak tekinted, megintcsak erosen felhasznalasfuggo. Lasd feljebb.
A vilagon mindenhol van escape-elendo elvalaszto karakter, mar csak a bevitel miatt is. Kulonben egy php-ben vagy akarmi masban megirt parser honnan tudna, hogy egy formbol erkezo "anya, apa, csirke" harmasbol az "anya, apa" egy cimkenek szamit vagy kettonek? Vagyis ezt a problemat semmikepp sem tudod megkerulni.
A tobb cimkere kereses valoban bonyolultabb az altalam javasolt rendszerben, de az egyszeru tartalommegjelenites cimkestul meg sokkal egyszerubb es gyorsabb, mivel csak egy tablat kell vegiggyalogolnia az adatbaziskezelonek. Ezert mondom, hogy alapvetoen a felhasznalas jellege donti el, hogy a tervezest milyen iranyba viszed es mit akarsz indexelni, normalformara hozod-e a tablat, es ha igen akkor melyikre. En terveztem mar ilyet is, meg olyat is. Aztan volt, ahol a felhasznalas nem igazolta vissza a teoriat (ott indult sok kereses ahol nem teljesitmenyre optimakoltunk, stb), vagyis hiba csuszott az _uzleti_ tervezesbe, ilyenkor sajnos ujra kell tervezni a rendszer bizonyos reszeit, vagy kimagyarazni a teljesitmenyromlast :)
Mivel az eredeti kerdes arra vonatkozott, hogy egy cimkezohoz altalaban milyen struktura szukseges, en batorkodtam a legegyszerubb megoldasbol kiindulni, amit persze a felhasznaloi igenyek fuggvenyeben mar a tervezesi szakaszban is a vegtelensegig lehet bonyolitani.
Es persze ismet hozzateszem - ebben a topicban nagon halkan - , hogy ezert szeretem en nagyon a PostgreSQL-t, mert ott alapbol van tomb tipusu mezo, es PL/PgSQL-ben csodasan lehet is vele dolgozni. Ott altalaban ezt hasznalom a cimkezesre.
Jellemzően akkor kell több tábla, ha 1-n kapcsolatod van, és jellemzően akkor használható 1 tábla, ha 1-1 kapcsolatod van (de ebben az esetben is általában 2 vagy több táblád van, kivéve ha performancia miatt denormalizálni kell). m-n kapcsolat esetében pedig jellemzően 3 tábla szükséges.
Mutass egy sémát amiben egy képhez több cimke is rendelhető a képek táblában, nincs benne több cimke mező, egy mezőben csak egy cimke szerepel és képenként csak egy sor van a táblában.
A szeparátorral elválasztott szöveges tárolás több okból is hibás, pl: 1) Nem indexelhető cimkék szerint. 2) A cimke szerinti lekérdezés plusz műveleteket igényel, azaz előbb a szeparátorok szerint részekre kell bontani a stringet vagy like-ot kell használni. Mindkettő sokkal költségesebb művelet, mint egy indexelt mezőt használni, de azt is megkockáztatom hogy még index nélkül is előnyösebb az egy mező-egy cimke tárolás. 3) Megerőszakolod az adatmodellt, azaz 1-1 kapcsolatra erőltetsz 1-n kapcsolatot. 4) Escapelni kell a szeparátor karaktert és ezt a későbbiekben kezelni kell, mert miért korlátoznád a felhasználót a címkében levő karakterek szempontjából? Pl. "2008. május" is lehet cimke, mint ahogy "anya, apa" vagy "#12", esetleg "én@budapest" is. 5) A több cimkére keresés bonyolultabb, pl. annyi like szükséges ahány cimkére keresel.
Összefoglalva: ezzel a megoldással nem spórolsz meg semmit (a join és a cimke tábla költsége elhanyagolható), viszont beviszel a rendszerbe egy halom problémát.
Hát ha engem kérdezel, én nem vok egy matematikus zseni, még csak elméleti szinten képzett programozó sem ... :-) Én gyakorlati szemszögből szoktam megpróbálni a problémákat megoldani.
(magyarul kitalálok valamit, kipróbálom és ha működik akkor használom...)
Ha jól értem arra akarsz kilyukadni, hogy a double számaimat lebegőpontosan tárolja a MySql és hiába én azt írom bele elvileg hogy mondjuk 11, amikor megkérdezem legközelebb hogy melyik rekordban egyenlő 11-el, akkor nem adja ki, mert szerinte az lehet hogy csak 10.9999999998...?
Mitől függ hogy milyen kicsi eltérés esetén tekintődik egyformának, vagy hogyan kerekítődik ?
Ez gyakorlatilag is okozhat gondot, vagy csak elméleti probléma? (nem vettem eddig észre hogy ez gond volna, postgres-en futogat itt ott ez az új double-s módi...)
Off-topik tesztkérdés: hogyan ellenőrizzük (lehetőleg gyorsan), hogy melyik az a legkisebb lebegőpontos szám, amelyre x=x+1 (a tárolás pontatlansága miatt, mielőtt valaki megkérdezné).
Ez egy olyan háttérrendszer amelyik pc-s kliens programok alá dolgozik. Több telephely egymástól függetlenül működő adatbázisait szinkronizálja időnként egymáshoz egy központin keresztül. Valamikor, amikor az ISDN még hűde gyorsnak számított és az állandó internet még nem volt természetes, egy konkrét cégnek csináltam, nekik megfelelt akkor ahogyan volt (ma is működik még valahogy), de azóta továbbgondoltam és mostanában újraírtam benne sok dolgot, hogy rugalmasabb legyen, eltűnjön belőle pár korábbi korlát... A double mező tulképpen egy minden adatíráskor folyamatosan növekvő jelző mező. Nem agyaltam sokat a típuson, ráböktem a legnagyobbra, hogy a lehető legtovább kitartson.
A lényeg, hogy az ORDER BY -al működik a dolog, így fog maradni.
A limit-tel kapcsolatban még nem lett konkrétan leírva, hogy az order by azért kell mert anélkül a rekordok sorrendje nem garantált. A rögzítés sorrendjét felejtsd el, szerintem a MySQL is végez néha karbantartást a fájlokban és olyankor könnyen előre kerülhet egy újabban rögzített rekord egy törölt helyére.
Azért akarok limitet, mert esetenként sokezer rekord is lehet az eredmény (amit a helyi gépen feldolgozok és letárolok más formátumba későbbi offline munkához) és nem akarom egyszerre áthúzgálni a kapcsolaton, hanem beállított adagonként, ciklusban...
Ez volna az értelme... Másképp kellene azt csinálnom ?
ha nem akarod sorbarendezni valami szerint akkor miert akarsz limit-et? Azaz MIRE akarsz limitet? Mert egy rendezetlen halmazra limit-et mondani, ugy hogy neked nem random kellenek a rekordok eleg butasag.
ha kiadsz egy ilyet: SELECT * FROM rendelo WHERE kod='XX' AND tolt > 200, ahol XX egyenló az ominózus sor egyedi kulcsával, akkor visszakapod a sort?
amúgy biztosan 200 van benne? mert a double miatt, ha pl. 199.9999999999999999999999999999999999999999 van benne, akkor simán 200-at látsz, de azért az valójában kisebb 200-nál
Közben tovább is próbáltam a dolgot.. Más táblán is tudom reprodukálni a dolgot, de úgy látom hogy csak akkor jelentkezik a hiba, ha a feltételes LIMIT 0,500 első eredménysora egyben a tábla legelső sora is... Ha már a második rekord lenne az első eredménysor, akkor jól működik a feltételes limit 0,500 is... érdekes.
Sajnos nem néztem el... Utánanéztem közben a mysql.com on is és másnak is előjött már ez a probléma, de nem láttam egyik új verzió leírásánál sem hogy megoldották volna. Én úgy vettem észre, hogy akkor marad el a legelső sor a limit 0,500 -ban, ha a where feltételben szerepel egy bizonyos indexelt mező.
Ha nem szűrök arra a mezőre, akkor a limit is jól működik. Az indexeléssel lehet valami gond, én megoldottam a problémát egy két plusz sorral, nem törtem rajta a fejem tovább.( Az index újra létrehozása nem segített)
load data infile '/var/www/meo/meoterm.txt' into table termek fields terminated by ' ' optionally enclosed by '"' ignore 1 lines (@a,@b,@c,@d,@e,@f,@g,@h,@i,@j,@k,@l,@m,@n,@o,@p,@q,@r,@s) set gyartott_mennyiseg=replace(@i,',','.');