Új hozzászólás Aktív témák
-
nyunyu
félisten
Indexet elég egyszer építeni, utána automatikusan karbantartja a DB, amíg el nem dobod a táblát.
Index karbantartás miatti insert, update időtöbblet sokkal kisebb, mint amit a selecteknél nyersz.
Sőt, sokmillió rekordos DBből törléskor baromi lassú tud lenni, ha a wherenél megadott feltételeket nem tudja legalább részlegesen kiértékelni valamelyik index használatával.
Olyankor gyorsabb, ha létrehozol egy indexet (pár perc alatt megvan!), majd a nagy mennyiségű adat törlése után eldobod az indexet.
-
nyunyu
félisten
Categoryt hiába indexálod, fészbúk operátor miatt mindig full table search lesz az eredmény...
Ha nem muszáj, ne nyomd a lájkot.
Nem tudom, melyik a gyakrabb a táblából olvasásnál, channel_id-re szűrés vagy a dátum szerinti rendezés, attól függően lehetne összetett indexet is használni, pl.:
CREATE INDEX table_ix1 ON table(channel_id, date);
Gyakrabban használt oszlopot tedd előre az indexben.Egy táblából olvasáshoz egyszerre csak egy indexet szoktak használni a DB kezelők, így hiába tennél minden oszlopra külön-külön, jobban jársz pár jól megválasztott összetett indexszel.
-
Taci
addikt
Bocsánat a sok posztért, de ebben a témában minden dolog új nekem, és szükségem van segítségre vagy megerősítésre.
Most pl. ebben:
Rátaláltam azEXPLAIN-re. Így most látom, hogy arowsértéke 4 (type: index), tehát működik az indexelés, mert nem olvassa be mind a ~500e rekordot, hogy dátum szerint sorba állítsa.
Még akkor is 4 arowsértékeEXPLAINmellett, ha a korábban írt hosszú-hosszú lekérdezést indítom (OR, AND, LIKE, NOT, %%). Szóval ez "papíron" nagyon jól néz ki most.Viszont ha ez már így elvileg működik, miért olyan dög lassú még mindig magán az oldalon? 10x gyorsabb, ha az eredeti 7500 rekordot rakja sorba indexelés nélkül, mintha ezt az 500e-t indexelve.
Hol és mit kellene még megnéznem?
-
Taci
addikt
Közben pár dolgot még megtaláltam:
A konzolban (phpMyAdmin) a táblát kibontva az indexek alatt ott van a létrehozott index.
Aztán ha rákattintok ("Indexek"), akkor a megfelelő mező mellett látok egy szürke kulcsot, szóval létre lett hozva.
Illetve alul látom a tulajdonságait is:
Egyedi: Nem
Csomagolt: Nem
Számosság: 7597 (a PRIMARY-nak ezzel szemben ~500e. Esetleg ez a szám mutatja majd, hol jár az indexelés?) (De most töröltem az indexet, és újra létrehoztam. És most 7341-et ír... Nem értem.)
Nulla: Igen (?) -
Taci
addikt
Illetve még egy kérdésem lenne:
Indexeltem elvileg, aztán a duplikálással felvittem 500e körülre a rekordok számát.
Viszont ugyanolyan lassú még mindig.- Most akkor nem vártam eleget, idő kell az indexeléshez, és csak később lesz gyorsabb?
- Vagy az indexelés csak az aktuálisan létező elemekre vonatkozik, a jövőbeniekre nem, ezért mondjuk minden új rekord felvétele után újra indexelni kellene?
Ezt mondjuk most meg is válaszolom magamnak, mert újra futtattam az indexelős parancsot, és azt írja, nem lehet, duplikált kulcsazonosító.
- Nyomon tudom követni valahol vagy valahogy az indexelés állapotát? Azt írják, hogy a user nem látja, de valahol biztos jegyezve van.(Kérlek, ha lehet, az előző kérdéseket is próbáljátok már megválaszolni.)
Köszönöm.
-
nyunyu
félisten
Próbálj meg indexet tenni a date mezőre.
CREATE INDEX table_date_ix ON table(date);Akkor nem próbálja meg felolvasni az egész táblát a memóriába 4 rekord kedvéért, hanem csak az indexet tölti be, és az alapján választja ki a következő négyet.
Sokmillió rekordos táblákat nem móka index nélkül használni...
-
Taci
addikt
És meg is van az eredmény... 2 millióig tudtam felvinni a duplikálást. Most pedig az apache logban ezeket találom:
Nincs elegendő memória-erőforrás a parancs feldolgozásához.
Érvénytelen cím hozzáférésére tett kísérlet.
Fatal error: Out of memory (allocated 467664896) (tried to allocate 16384 bytes)És nem is tölt be semmit az adatbázisból.
Jelenleg ez csak egy desktop server, csak tesztelni.
De előfordulhat ilyen hiba a szolgáltatónál is?
Az én kódomban van a hiba?Amúgy nem egy nagy lekérdezés volt, csupán ennyi:
SELECT * FROM table ORDER BY date DESC LIMIT 4És erre dobta a fenti hibákat.
Nekem kell javítani/változtatni valamit, vagy ez a DesktopServer korlátjai miatt van, és a normál szerveren (szolgáltató) ezzel nem lesz gond?
Köszi.
Upd.: 1 milliónál is ugyanez a baja. De 500ezernél már lassan, de végzi a dolgát.
-
martonx
veterán
-
martonx
veterán
Full Text search-öt előbb a DB-ben be kell kapcsolni fel kell paraméterezni (az általad linkelt fisfos hosting cégeknél pláne erősen kérdéses, hogy be tudsz-e ilyet kapcsolni). Bevallom én még sose használtam, mert nem kellett. Igaziból, ha nem sok millió, egészen nagy méretű szövegben kell keresned, akkor szerintem a Like is simán megteszi.
Full text search helyett én pl. hehe a Google-t használom a weboldalaimon, amiket a Google egyébként is indexel
Programmable Search Engine | Google Developers
Így nem az én DB-mnek kell belegebednie az oldalon keresések kiszolgálásába, hanem a Gugliénak, ráadásul ingyen.
-
Taci
addikt
Úgy látom, a PHP-oldali résszel készen vagyok (nagy meglepetésemre).
Viszont a kereséshez (és szűréshez) kapcsolódó lekérdezések még mindig a "régi csúnyák":
Így néz ki jelenleg, ha keresést indítok 3 különböző szóra:
SELECT * FROM the_only_one_tableWHERE((title LIKE '%kereso_szo_1%'ANDtitle LIKE '%kereso_szo_2%'ANDtitle LIKE '%kereso_szo_3%')OR(description LIKE '%kereso_szo_1%'ANDdescription LIKE '%kereso_szo_2%'ANDdescription LIKE '%kereso_szo_3%'))ANDid NOT IN (672,467,439,395,325,143,10,156)ORDER BY date DESCLIMIT 4(az id NOT IN részt csak azért hagytam benne, hogy megmutassam, hogy megfogadtam a tanácsaitokat, és így valóban kulturáltabb az egész
)A kereséshez (és ugyanilyen elven (LIKE %%-kal) működik a szűrés is):
Az ajánlás alapján rákerestem a full text search-re. Ott elsőnek a CONTAINS-t találtam. De kézzel (phpMyAdmin-ban a konzolban) sem adott vissza találatot:WHERE CONTAINS ((title, description),'"kereso_szo_1" AND "kereso_szo_2" AND "kereso_szo_3"')Láttam keresési találatokat
MATCH-re,MATCH AGAINST-re, de a leírásuk sem győzött meg, hogy ezeket kellene használnom.Szóval martonx tanácsát megfogadva inkább rákérdezek, hogy hogyan lehetne megoldani a keresést/szűrést a a
LIKE %%használata nélkül?
Engem -tapasztalatlant- persze nem zavar, csak ugye írtátok, hogy rém pazarló. A LIKE-nál keresés miatt pedig muszáj vagyok a %%-ot használni, mert a szöveg bármelyik pontján lehetnek a keresett szavak.Köszi!
-
nyunyu
félisten
Azt nem tudod belegyógyítani a közös táblát író insertbe, hogy HTML requestben megkapott domain függően töltse ki a forras mezőt?
Illetve a weblapnak választ adó selectekbe is?insert into ujtabla (forras, mezo1, mezo2...)
select
case when domain = 'elsoweblapom.hu' then 'forras1'
when domain = 'masodikweblapom.hu' then 'forras2'
end forras,
mezo1,
mezo2,
...De akkor már elegánsabb lenne felvenni egy szótár táblát, amiben megadod a domain - forrás összerendeléseket, és ez alapján joinolod a selecteket.
Így már nem kell majd hozzányúlni a kódhoz amikor új forrást veszel fel, hanem csak egy új sort kell felvenni a forrasok táblába, és működni fog az új weblap is.create table forrasok (
domain varchar(100),
forras varchar(10)
);
insert into forrasok (domain, forras)
values ('elsoweblapom.hu','forras1');
insert into forrasok (domain, forras)
values ('masodikweblapom.hu','forras2');
insert into ujtabla (forras, mezo1, mezo2)
select f.forras, v.mezo1, v.mezo2
from html_valasz v
join forrasok f
on f.domain=v.domain
...
select t.*
from ujtabla t
join forrasok f
on f.domain = html_domain
where t.forras = f.forras
and ...Remélem érthető a gondolatmenetem.
Egyébként meg az ilyen mellényúlásokból tanul a legtöbbet az ember.
-
martonx
veterán
Ezt fogd fel tanulópénznek, és igen, mindenképp írd át normálisra a táblastruktúrát. Legalább ezzel is tanulsz.
Illetve máskor lehet nem árt kérdezni, mielőtt magadtól kitalálsz valami butaságot, és 6 hónapig rossz irányba mész (jó persze sokszor a kérdezéshez is már kell egy alap tudás...).Egyúttal szólok előre, hogy az ilyen vicc tárhelyeknél, majd még csak ezután fog kezdődni a kálváriád, amikor ki fog derülni, hogy MariaDB-t nem támogatnak

A helyedben egyből a felhőt céloznám meg (ok, ott meg nem évi 10K HUF lesz a hosting, bááár lehet, lusta vagyok utána nézni a DB áraknak). -
Ispy
nagyúr
Hogy röviden válaszoljak: ha szar, át kell írni. Pont.
Nem te vagy a történelembe az első, aki lyukra futott, ne aggódj, ráadásul kezdő vagy. Ez a hiba most egy tapasztalat, az ember így tud fejlődni, senki sem úgy kezdi, hogy miden kódja tökéletes már a legelső kódsortól kezdve. Ne sajnáld az időd a hibáid feltárására és kijavítására, mert persze, ez most így könnyebbnek tűnik, de így csak a szönyegalá sepred a dolgot és később is lesz mindig fájdalommentesebb út.
-
bambano
titán
jó lett volna, ha leírod, hogy milyen adatbáziskezelőről van szó.
a későbbi hsz-eid alapján ha találgatnom kellene, azt írnám, hogy mysql.
miért nem postgresql?
igen, jól érted. a jól normalizált adatszerkezet lényege, hogy később sem kell belenyúlni. ha most rakás táblád van és azt később bővíteni kell, akkor a lekérdezésekbe is bele kell nyúlni, meg mindenbe.
a lényeg, hogy el kell választani a logikai sémát a tárolási sémától. a logikai séma azt mutatja meg, hogy hogyan kell kinézzen az adatbázis, miután normalizáltad. a tárolási séma meg azt, hogy indokolt esetben miben tér el a logikai sémától.
amit emlegettek mások is, ha nagy a tábla, akkor lehet particionálni a táblát. ráadásul ha külön tablespace-be teszed a partíciókat, akkor a diszk elérés is gyorsulni fog (régen a mysql tudott raid0-t, de kivették belőle...)
mondjuk az is relatív, hogy kinek mi a nagy adatbázis. a postgesql párszázmillió rekorddal még szépen elgurul. utána kell elkezdeni tákolni a tárolórendszert hozzá.
-
nyunyu
félisten
Gondolom utólag akarsz arra is szűrni, hogy honnan származik az adat.
Most ha quick&dirty megoldást akarsz a meglévő táblákban lévő rekordok egy helyre lapátolására, akkor:
create table ujtabla as
select 'forras1' as forras, t1.*
from tabla1 t1;
insert into ujtabla
select 'forras2' as forras, t2.*
from tabla2 t2;
...
insert into ujtabla
select 'forras5' as forras, t5.*
from tabla5 t5;+ az eddigi kódban minden insertbe beleteszed, hogy az új rekordoknál mivel töltse a forras mezőt.
+ az eddigi táblaneveket mindenhol lecseréled ujtabla-ra
+ létrehozod az eddigi táblákra vonatkozó indexeket ujtabla-ra.Ekkor ha mondjuk külön akarnál selectálni a kettes rendszerből, akkor ezután így fog kinézni:
select *
from ujtabla
where forras='forras2'
and ...
order by date desc;lletve PHP oldalról megnézni, hogy az új struktúrájú lekérdezésben hogyan tudnám hatékonyan használni a bind_param-ot. (Ha kell/lehet-e egyáltalán.)
Nem vágom a PHPt, de gondolom a mezők bindelésénél ki kell cserélni a táblanevet az újra, valamint az új forras mezőnek fixen megadni egy értéket. (Mittudomén kettes webshopnál azt, hogy 'forras2', vagy aminek elnevezted)
-
nyunyu
félisten
De amúgy tényleg érdekelne, hogy miben/mennyivel "rosszabb", ha több táblában vannak az adatok. Nyilván a sebesség az egyik válasz, ez biztos. De érdekelne, miben még.
Leginkább a kód karbantarthatóságról szól a felvetésünk. (meg olvasni, átlátni is könnyebb a rövidebb, egyszerűsített kódot)
Most ha bejön egy új alrendszer/forrás, akkor kézzel definiálsz neki egy új táblát, arra indexeket, meg a meglévő kódbázisban az összes union-os selectet ki kell bővíteni +1 ággal, hogy az új forrást is visszaadja.
Plusz szopni fogsz, ha bármelyik táblába fel kell venni egy plusz mezőt, mert akkor kézzel alter table az összesre, hogy az unionok továbbra is működhessenek...Míg egy táblánál csak az új forrás adatbetöltő rutinját kell megírnod, ami egy új azonosítóval szúrja be a meglévő táblába a rekordokat.
Plusz oszlop igény esetén meg elég egy táblát alterelni, nem fog elszállni a kód (ha ki van mindenhonnan irtva a select *
) -
nyunyu
félisten
Úgy szeretném megcsinálni, hogy utána szerkezeti változás miatt ne kelljen már "soha" belenyúlni, ezért veszem a fáradságot és időt és átírom, ezzel nincs baj. Csak érteni is szeretném a miértjét.
Ha most nem léped meg a refaktort, és később kiderül, hogy valamelyik táblába fel kell venned pár plusz oszlopot, akkor az összesbe veheted fel egyesével ugyanazokat, ugyanabban a sorrendben, különben hibával elszáll az összes union-os lekérdezésed!
Mondjuk ebből a szempontból a select *-os slendriánság sem egy életbiztosítás

Sokkal elegánsabb, és hibatűrőbb, ha egyesével felsorolod a lekérdezendő oszlopokat + insertnél a beszúrandó tábla oszlopait.magyarul mindenhol így nézzen ki a kód:
insert into tábla (oszlop1, oszlop2, oszlop3)
select oszlop1, oszlop2, oszlop3
from tábla2;Ez nem fog megborulni, ha bármelyik tábla szerkezete módosul.
-
nyunyu
félisten
Akkor meg pláne most kéne meglépni az egy táblára átállást, mert 20 táblánál már sokkal több időt fog igényelni a refaktorálás.

Amire kell csak figyelni: összes a táblába szúró insertnél legyen kitöltve a forrásrendszer azonosító.
Aztán ha alrendszerenként nagyon sok adat van, és az adatbázis licenszed is megengedi, akkor el lehet gondolkozni a forrásrendszer azonosító menti partícionáláson, amikor partíció kulcsonként külön táblateret használ, és mindegyiknek külön épít indexeket.
Ekkor konkrét azonosítóra szűrve ugyanúgy viselkedik a nagy tábla, mintha önálló táblája lenne az alrendszernek viszonylag kicsi adatmennyiséggel, ha meg nem szűrsz, akkor az alrendszerek tábláinak unióját látod. (ez utóbbi nem annyira hatékony, ha a partíciókulcs nincs a join/where feltételben!) -
nyunyu
félisten
Az 5 táblában 5 különböző forrásból származó bejegyzések vannak, jellemzően több száz (idővel több ezer), ezért vannak már eleve külön táblákba mentve.
Erre felesleges 5 táblát fenntartani, elég lenne egy tábla is, amibe felveszel egy pár karakteres új oszlopot, amibe az forrás azonosítóját írod, aztán ha forrásra kell szűrni, akkor beírsz plusz egy where feltételt a lekérdezésbe.
Amúgy meg kimaradt a külső select:
SELECT *
FROM
(SELECT * FROM table1
UNION ALL
SELECT * FROM table2
UNION ALL
SELECT * FROM table3
UNION ALL
SELECT * FROM table4
UNION ALL
SELECT * FROM table5)
WHERE ID NOT IN (...)
ORDER BY date DESC
LIMIT 4; -
'NOT IN' elég pazarló (legalább is az én ismereteim szerint), persze lehet, hogy a modern motorok már átalakítják kevésbé lassabbakra.
A LIKE-ok meg szerintem mindegy milyen scope-ban futnak. Simán egybe lehet rakni az összes táblát és utána szűrni:SELECT * FROM (
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
UNION ALL
SELECT * FROM table3
UNION ALL
SELECT * FROM table4
UNION ALL
SELECT * FROM table5
)
WHERE ((title LIKE '%szoveg%') OR (description LIKE '%szoveg%'))
ORDER BY date DESC -
nyunyu
félisten
Mi a ráknak van öt, tökegyforma táblába szétszedve az adat?
Teljesen felesleges, hacsak nincs sokmillió rekord, és időnként másik táblába archiváltok.
Gyorsan hízó logokhoz szerintem felesleges az unionnal bohóckodni, egyszerre úgyis csak egy logban akarsz keresni, hiszen nagyjából be tudod lőni, milyen dátum intervallumot akarsz vizsgálni.Meg az order by-t sem értem, mert ebben a formában csak az ötödik táblát rendezi csökkenőbe.
Először kapod az első táblát rendezetlenül, aztán a másodikat, aztán a harmadikat... végül az ötödiket rendezve.
Ha fontos az időben csökkenő rendezés, akkor én tennék egy select * from ( ) order by date desc-et az unionok köré. -
Ispy
nagyúr
Ez a megoldás azért lassú, mert csináltál egy Descartes-szórzatot a két táblából, azaz minden halmaz minden elemét összeköti szépen minden halmaz minden elemével (vesszővel felsorolás). A helyes ahogy írtad is az union, csak figyelni kell, mert ha nincsen all, akkor az azonos rekordokat csak egyszer hozza a halmazokból.
Új hozzászólás Aktív témák
- Luck Dragon: Asszociációs játék. :)
- Házimozi belépő szinten
- AMD GPU-k jövője - amit tudni vélünk
- Itt a Galaxy S26 széria: az Ultra fejlődött, a másik kettő alig
- Samsung kuponkunyeráló
- PlayStation 5
- sziku69: Fűzzük össze a szavakat :)
- AliExpress tapasztalatok
- Samsung Galaxy A52s 5G - jó S-tehetség
- Google Pixel topik
- További aktív témák...
- ÚJ Samsung Galaxy Z Fold 7 16 GB/1TB Jetblack
- Üzletből, garanciával, HP ZBook Furry 15 G8 i7-11850H/32GB RAM/512GB SSD/RTX A2000/FULL HD IPS
- Victus 16-r0013sl 16.1" FHD IPS i7-13700H RTX 4070 32GB 512GB NVMe gar
- Iphone 12 pro max
- ThinkPad P17 Gen2i 17.3" FHD IPS i7-11850H RTX A3000 32GB 512GB ujjlolv IR kam gar
- Apple MacBook Pro 14 (2021) M1 Pro 16GB/500GB használt, szép állapot 87% akku (323 ciklus)
- HP Elitebook X360 830 G7,Multi-Touch 2 az 1-ben,i5-10310U,16GB DDR4,256GB SSD,WIN11
- Telefon felvásárlás!! iPhone 16/iPhone 16 Plus/iPhone 16 Pro/iPhone 16 Pro Max
- DELL PowerEdge R630 rack szerver - 2xE5-2650v3 (20 mag / 40 szál, 2.3/3.0GHz), 32GB RAM, 66921Ft+ÁFA
- AKCIÓ! Dell Latitude 3430 üzleti notebook - i5 1235U 8GB DDR4 512GB SSD Intel Iris Xe WIN11
Állásajánlatok
Cég: Laptopműhely Bt.
Város: Budapest




