Hirdetés

2024. április 19., péntek

Gyorskeresés

Útvonal

Fórumok  »  Szoftverfejlesztés  »  SQL kérdések (kiemelt téma)

Hozzászólások

(#5001) bambano válasza kw3v865 (#4995) üzenetére


bambano
titán
LOGOUT blog

ezt nem lehet megoldani.
példa: legyen három timestampod, az első és a harmadik egymástól 1 perc 40 másodperc távolságra. A középső meg félúton. Akkor a középső melyikhez tartozik?

egyébként timestampokat ki lehet vonni egymásból, timestamp lesz az eredmény, amit lehet konvertálni egész számmá.

Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis

(#5002) Ispy válasza bambano (#5001) üzenetére


Ispy
veterán

Meg lehet ezt oldani, csak nem egy viewban.

"Debugging is like being the detective in a crime movie where you're also the murderer."

(#5003) bambano válasza Ispy (#5002) üzenetére


bambano
titán
LOGOUT blog

figyelek!

Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis

(#5004) Ispy válasza bambano (#5003) üzenetére


Ispy
veterán

El kell indulni a legkisebb dátumtól, ha jön az első dátum, ami 60 mp-en kívül van, akkor az egy csoport és indul újra a loop. Most azon lehet vitázni, hogy kisebb mint 60 vagy kisebb egyenlő. Ha megvan minden group, akkor meg kell határozni a group min és max értéke között az eltéréseket, azokat a groupokat meg ki kell szórni, ahol count(*)=1.

Már ha felfogtam mi a feladat...nem volt egyértelmű nekem az alap def.

[ Szerkesztve ]

"Debugging is like being the detective in a crime movie where you're also the murderer."

(#5005) Ispy válasza Ispy (#5004) üzenetére


Ispy
veterán

Vagy ha bármely elemhez vonatkoztatva kell lekérni, akkor meg cross join -nal kell csinálni egy Decrates-szórzatot úgy, hogy datum1 minusz datum2 és ahol a különbség -60 és +60 között van azokat kiszűrni, és akkor megkapjuk egy táblázatba, hogy mely dátumokhoz mely dátumok vannak az 1 perces intervallumba előre, hátra.

Csak ettől lehet meghajlik a vas....

[ Szerkesztve ]

"Debugging is like being the detective in a crime movie where you're also the murderer."

(#5006) kw3v865 válasza Ispy (#5004) üzenetére


kw3v865
senior tag

Jól gondolod. Végigmenni a sorokon (timestamp növekvő sorrendben van), és csoportosítani őket egy új view-ba (aztán summázni, és egyéb aggregáló műveletek végezni rajtuk). Úgy szeretném, hogy az egyes csoportok első és utolsó időpontja között max. 1 perc legyen a különbség. Tehát ha valamelyik érték túllépi az 1 percet, akkor az már a következő csoportba kell, hogy tartozzon, és akkor ismét 0-ról indul az "óra".

(#5007) Ispy válasza kw3v865 (#5006) üzenetére


Ispy
veterán

Akkor meg egy tárolt eljárás kell és egy cursor, vagyis ennek a megfelelője postgre sql-ben.

Egy group counter változó blabla, nem nehéz egy ilyen loopot összerakni. Ms sqlben lehet inkább egy tábla függvényt csinálnék erre.

[ Szerkesztve ]

"Debugging is like being the detective in a crime movie where you're also the murderer."

(#5008) kojakhu válasza kw3v865 (#4995) üzenetére


kojakhu
újonc

Hali, Lehet erre gondolsz. Addig egy entry egy csoport, amíg a timestamp gap nagyobb nem lesz mint 1 perc. Csoportokban meg lehet N db entry is amíg a gap nem túl nagy.

Ezt így lehet, pl.
Itt az SQLFiddle : [link]

Kód:

Setup:

create table t (dt timestamp);
-- group 1
insert into t values (current_timestamp - interval '10' second);
insert into t values (current_timestamp);
insert into t values (current_timestamp + interval '10' second);
-- group 2
insert into t values (current_timestamp + interval '120' second);
insert into t values (current_timestamp + interval '130' second);
-- group 3
insert into t values (current_timestamp + interval '220' second);
insert into t values (current_timestamp + interval '230' second);
Lekérdezés:

WITH
diffs AS (
SELECT dt
, LAG(dt) OVER (ORDER BY dt) AS prevdt
, LEAD(dt) OVER (ORDER BY dt) AS nextdt
, ROW_NUMBER() OVER (ORDER BY dt) AS rn
FROM t
) -- diffs
, group_gaps_and_flags AS (
SELECT v.*
, dt-prevdt AS prev_gap
, CASE WHEN prevdt IS NULL OR dt-prevdt > interval '1' minute
THEN 'Y'
END AS group_start_flag
, nextdt - dt AS next_gap
, CASE WHEN nextdt IS NULL OR nextdt-dt > interval '1' minute
THEN 'Y'
END AS group_end_flag
, CASE WHEN prevdt IS NULL OR dt-prevdt > interval '1' minute
THEN rn
END AS rn_if_start
FROM diffs AS v
) -- gaps_and_groups
, groups AS (
SELECT v.*
, MAX(rn_if_start) OVER (ORDER BY dt) -- ROWS BETWEEN UNBOUNDED_PRECEEDING AND CURRENT_ROW
AS my_group
FROM group_gaps_and_flags AS v
) -- groups
-- .
-- SELECT * FROM groups; -- separator for testing
-- .
SELECT my_group, MIN(dt), MAX(dt), COUNT(dt)
FROM groups
GROUP BY my_group
ORDER BY my_group


sorry, nem tudom még ezen a fórumon hogy kell kódot beszúrni jól...

(#5009) bambano válasza kojakhu (#5008) üzenetére


bambano
titán
LOGOUT blog

nem, nem erre gondolt.

Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis

(#5010) kojakhu válasza bambano (#5009) üzenetére


kojakhu
újonc

Közben meg is írta h mi a pontos elvárás, de a kódolástól nem láttam :)

Itt van, ami szerintem már helyes, csak azért h hátha meg lehet mégis csinálni.

Viszont performancia miatt nem lesz használható.
Max akkor, ha valahogy a sorok számát a rekurzív részben lehet limitálni. Pl ha lehet tudni, hogy max mekkora gapek vannak a logok között (ezt is ki lehet számolni akár), vagy esetleg az előző munkámmal lehet összeszerelni úgy h az ott előálló csoportokban kell csak részcsoportokat képezni.

Szóval brahiból itt az újabb SQLFiddle link
Pls valaki mindenképpen válaszoljon (ha jó a megoldás, ha nem), mert a blogon "újoncként" nem írhatok csak 1-et amíg nincs rám válasz...

Setup:
create table t (dt timestamp);
-- group 1
insert into t values (current_timestamp);
insert into t values (current_timestamp + interval '10' second);
insert into t values (current_timestamp + interval '59' second);
-- group 2
insert into t values (current_timestamp + interval '70' second);
insert into t values (current_timestamp + interval '71' second);
insert into t values (current_timestamp + interval '129' second);
-- group 3
insert into t values (current_timestamp + interval '200' second);
insert into t values (current_timestamp + interval '210' second);
insert into t values (current_timestamp + interval '220' second);
insert into t values (current_timestamp + interval '259' second);
-- group 4
insert into t values (current_timestamp + interval '260' second);
insert into t values (current_timestamp + interval '261' second);

Lekérdezés:
WITH RECURSIVE rd(grp, mindt) AS (
SELECT 1 AS grp
, MIN(dt)
FROM t
UNION
SELECT rd.grp+1 AS grp
, FIRST_VALUE(t.dt) OVER (ORDER BY t.dt)
FROM t, rd
WHERE t.dt >= rd.mindt + INTERVAL '1' MINUTE
) -- rd
, grpd AS (
SELECT grp
, t.*
, MIN(dt) OVER (PARTITION BY grp) mindt
, MAX(dt) OVER (PARTITION BY grp) maxdt
, COUNT(*) OVER (PARTITION BY grp) cnt
FROM rd, t
WHERE t.dt >= rd.mindt AND t.dt < rd.mindt + INTERVAL '1' MINUTE
) -- grpd
SELECT v.*
, maxdt-mindt AS grp_duration
FROM grpd AS v
ORDER BY dt

[ Szerkesztve ]

(#5011) kw3v865 válasza kojakhu (#5010) üzenetére


kw3v865
senior tag

Megnéztem, ez most úgy tűnik, hogy jó! :K Köszönöm a segítséget! A teljesítménye meg majd látszik a gyakorlatban. Majd ezt ki kell még egészítenem néhány dologgal, aztán kiderül mennyire lesz gyors.

(#5012) kw3v865


kw3v865
senior tag

Sziasztok!

Ismét egy PostgreSQL-es kérdés, ezúttal már függvényt írok, PL/PgSQL nyelven: A függvényemben több select-et is futtatok, de előtte "be akarom cache"-elni egy lekérdezés eredményét, hogy később már sokkal gyorsabb legyen a többi select (leszűkíteni a sorok számát nagyon jelentősen).

Tehát kvázi ideiglenes táblát szeretnék létrehozni, amit csak az adott függvényen belül használok. CTE-vel sajnos nem megy, mert egy CTE-t csak egy select tud felhasználni, én pedig konkrétan 9 select-et fogok használni.

Próbáltam TEMPORARY TABLE-lel, de az lassúnak tűnik. A ROWTPYE vagy RECORD típus tökéletes lenne, de sajnos csak egy sort tud tárolni, így az nem jó. Tábla típus pedig sajnos nincs.
Van esetleg valami tippetek hogyan lehetne ezt a leghatákonyabban megcsinálni? Itt most nagyon fotnos lenne a jó teljesítmény, hiszen rendkívül időkritikus a dolog.

[ Szerkesztve ]

(#5013) bambano válasza kw3v865 (#5012) üzenetére


bambano
titán
LOGOUT blog

két megoldási irányzat van:
1. az álmoskönyvek szerint nincs olyan, hogy elég ram van.
2. ha temp táblát csinálsz, érdemes elolvasni a kottát, például az unlogged részt, mert van gyorsítási lehetőség.

Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis

(#5014) nyunyu válasza kw3v865 (#5012) üzenetére


nyunyu
félisten

Ezen nem kell sokat gondolkozni, csinálsz egy táblát, teszel rá megfelelő index(ek)et, belehajítod az eredményhalmazt, majd az összes későbbi selectben azt használod/joinolod.
Ha túl sok lépésből áll az algoritmus, akkor na bumm, lesz 3-4-5 köztes táblád.

Hello IT! Have you tried turning it off and on again?

(#5015) martonx válasza kw3v865 (#5012) üzenetére


martonx
veterán

A temp tábla nem szabadna, hogy lassú legyen. Hacsak nem felejtkeztél el arról, hogy a temp táblára is ugyanúgy rá kell pakolni az indexeket.

Én kérek elnézést!

(#5016) kw3v865 válasza martonx (#5015) üzenetére


kw3v865
senior tag

Akkor is kell az index a temp táblára, ha csak 15 rekordot tartalmaz? Ennél nem nagyon lehet benne több sor. Igazából nem látok most észrevehető javulást ezzel a temp táblás cache-eléssel. Nem erre számítottam, de ez van. Ennél a függvénynél minden egyes ms sokat számít. Ha már 1 ms-sel meg tudnám javítani a futásidejét, az is eredmény lenne. Valószínűleg a minimum 9 olyan select miatt nem lehet gyorsabb, amelyek táblát is használnak, azokon már nem tudok gyorsítani.

Explain analyse-szel sajnos nem tudom kideríteni mely része a lassú a függvénynek, tehát egyelőre csak tippelgetni tudok min lehetne még optimalizálni. Talán azt próbálom még meg, hogy ami nem feltétenül szükséges, azt kiteszem a C#-ba, és az eredményt paraméterként adom meg ennek a függvénynel. Bár ezek nem túl összettt műveletek.

(#5017) nyunyu válasza kw3v865 (#5016) üzenetére


nyunyu
félisten

Ja, hogy a sokmilliós táblán nincs index?
Úgy biztos lassú lesz.

Ha meg dinamikus SQLt vagy egyéb hasonló külsőleg futtatandó varázslatokat hívsz, akkor meg pláne lemondhatsz az 1-2 másodperc alatti futásidőről.

Ha meg annyira időkritikus, akkor nincs mese, alá kell pakolni a vasat.
Esetleg elgondolkozni azon, hogy tetőfedéshez nem malteros kanalat kéne használni, mert azzal tényleg nem lehet haladni, akárhogy optimalizálod a processt.

Hello IT! Have you tried turning it off and on again?

(#5018) kw3v865 válasza nyunyu (#5017) üzenetére


kw3v865
senior tag

Néhány 100 ezer rekord van az "alap" táblában, természetesen indexelve van. Csak a temp táblára nem raktam indexet, mondván 10-20 rekordra minek.

(#5019) nyunyu válasza kw3v865 (#5018) üzenetére


nyunyu
félisten

Akkor nézd meg most, mit csinál a query plan, aztán tegyél indexet a táblákra a join feltételek mentén, aztán ismét nézd meg mit csinál a query plan :DDD

Meg sokszor a statisztika gyűjtés is hasznos tud lenni nagyobb számítások előtt, hogy a DB optimalizálónak legalább valami halvány fogalma legyen arról, hogy melyik tábla mekkora, mert másképp célszerű csinálnia a joint kicsi tábláknál, mint nagyoknál.

[ Szerkesztve ]

Hello IT! Have you tried turning it off and on again?

(#5020) Ispy válasza kw3v865 (#5018) üzenetére


Ispy
veterán

Az is lehet a baj, ha a szerverbe lassú HDD van mondjuk egy gyors SSD-hez képest, mert ilyenkor jobban futnak azok a selectek, amiket ízomból át lehet tolni a memórián, mint azok, amik a HDD-hez nyulnak, mondjuk egy temp tábla pont ilyen.

"Debugging is like being the detective in a crime movie where you're also the murderer."

(#5021) nyunyu


nyunyu
félisten

Egyébként meg lehet, hogy a tákolt eljárás ezredmásodpercekre kireszelése helyett inkább a folyamatot kéne átnyálazni, hogy az mennyire optimális, azzal valószínűleg SOKKAL többet nyernél. :DDD

Egy korábbi combos adatmigrációs projekten anyáztak velem állandóan a nagy adatmennyiségen lefutó sok adatellenőrző szkript "lassúsága" miatt.
(Én reszelgettem a szkripteket azon a projekten)

Aztán következő projekten újrahasznosítottuk az egész adatellenőrző keretrendszert, csak annak a gazdája már nem volt a csapatunk része, így elmélyedhettem a kolléga kódjában, és tele volt kurzorokkal, meg dinamikusan összerakott SQL hívásokkal :W
Egészben az volt a legszebb, hogy az összes rekordra egyesével hívta meg az ellenőrző szkripteket.

Azt meg tudni kell, hogy Oracle alatt egy exec 'select 1 from dual;' akkor is másfél másodpercig tart, ha fejreállsz közben...

Végeredmény az lett, hogy az egyesével futtatott szkripteket összefűztem egy clobba, aztán az lett dinamikusan futtatva.
Plusz kivettem a kurzort az egész elől, mert az ellenőrző szkriptek eleve úgy voltak megírva, hogy egész táblára futottak, így egy százezres táblán elég volt őket egyszer meghívni, nem kellett rekordonként külön-külön...

Eredmény? 20 perc helyett lefutott az egész 15 másodperc alatt.

Tanulság?
Ne engedj Java/C/C# programozót SQLt "kódolni", mert az teljesen más műfaj.
(Pláne, ha natív SQL helyett Hibernate-tel vagy LinQ-el súlyosbítja :W)

Kiváncsi lettem volna, hogy a keretrendszer 2.0-át visszaportolva a légycsapó projektbe, mennyi ideig tartott volna a 3 betűs nagybank összes telefonvonalának adathelyesség ellenőrzése az eredeti 12 óra helyett :DDD

[ Szerkesztve ]

Hello IT! Have you tried turning it off and on again?

(#5022) Ispy válasza nyunyu (#5021) üzenetére


Ispy
veterán

Nekem is volt ilyen projektem, amikor a 4. egymásba fűzött loopot probáltam megérteni, na akkor kidobtam az egészet és újraírtam. Eredmény: a havi elszámolás, ami korábban 6 órát futott lett 5 perc.

"Debugging is like being the detective in a crime movie where you're also the murderer."

(#5023) martonx válasza nyunyu (#5021) üzenetére


martonx
veterán

Én mint C# fejlesztő, aki mellette sokat SQL-ezett is régen, ezzel nem értek egyet.
Csak szimplán nem kell hülyének lenni, és el kell mélyedni az egyes nyelvekben.
Az SQL totálisan más logikai megközelítést igényel, mint egy normális programnyelv. De mindkettő megérthető, megtanulható.
Több olyan kollégáról is tudok, akiknél nagyon szépen megfér egymás mellett a két világ ismerete, harmonikus használata.

Én kérek elnézést!

(#5024) #68216320 válasza martonx (#5023) üzenetére


#68216320
törölt tag

Sorry, nem válasz akart lenni.

Sziasztok.

Kicsit off a téma, de nem teljesen.
Tudtok olyan free web api url-t, ami az EB meccsek eredményeit folyamatosan visszaadja mondjuk json vagy valami hasonló formátumban? Szeretnék egy parser-t csinálni rá, hogy saját db-ben tudjam használni ezeket.

[ Szerkesztve ]

(#5025) nyunyu válasza #68216320 (#5024) üzenetére


nyunyu
félisten

Kérdés, jogilag ez mennyire számít közvetítésnek.
Közvetítési jogokat ugye fizetősen méri az UEFA...

Hello IT! Have you tried turning it off and on again?

(#5026) #68216320 válasza nyunyu (#5025) üzenetére


#68216320
törölt tag

Szerintem az eredmények nem tartoznak müsorszórási jogkörbe.

(#5027) bhonti válasza #68216320 (#5024) üzenetére


bhonti
tag

Esetleg pushalert vagy rss. Pl. a csakfoci.hu oldalról...

http://1kis.info.hu - Informatikus mindenkinek... 501065096 balazs@honti.tech

(#5028) #68216320 válasza bhonti (#5027) üzenetére


#68216320
törölt tag

Rss jó ötlet, köszi. Megnézem mik a lehetőségek.

(#5029) RoyalFlush


RoyalFlush
őstag

Sziasztok!

A segítségeteket szeretném kérni egy lekérdezés összeállításában. :R Oracle PL/SQL.

RENDELES_DATUM DATE
TERMEK VARCHAR2(255)

RENDELES_DATUM TERMEK
2020-06-15 Termék1
2020-06-14 Termék1
2020-06-14 Termék2
2020-06-14 Termék2
2020-05-25 Termék1
2020-05-25 Termék1
2020-05-10 Termék2
2020-04-05 Termék2
2020-04-01 Termék1
...

Azt kellene kimutatni havi bontásban egy időszak intervallumra vonatkozóan, hogy a termék1-ből és a termék 2-ből együttesen mennyit rendeltek.

Példa az outputra:
2020-06 4 db
2020-05 3 db
2020-04 2 db
2020-03 15 db
2020-02 34 db
2020-01 22 db
...

Előre is köszönöm szépen! :R :R

[ Szerkesztve ]

“Mankind invented the atomic bomb, but no mouse would ever construct a mousetrap.” Albert Einstein

(#5030) tm5 válasza RoyalFlush (#5029) üzenetére


tm5
tag

SELECT TRUNC(RENDELES_DATUM, 'MONTH') HONAP, COUNT(*) DARAB
FROM TABLA
WHERE TERMEK = 'Termék2'
GROUP BY TRUNC(RENDELES_DATUM, 'MONTH')
ORDER BY 1 DESC

(#5031) Taci


Taci
addikt

Sziasztok!

Van rá mód esetleg, hogy valahogy (egyszerűen) sokszorosítsam az adatbázisom (az egyik tábla) tartalmát?

Jelenleg kb. 4e elem van benne, és szeretném megnézni, hogyan viselkedne mondjuk 400e vagy 4 millió elemnél. Mennyire lassulna be stb.

Meg lehet ezt oldani egyszerűen? (Nem kell a tábla semmire, teszt fázisban van csak, törlöm, és újra feltöltöm, ha az kell majd.)

Köszi.

(#5032) bambano válasza Taci (#5031) üzenetére


bambano
titán
LOGOUT blog

az insert képes selectből insertálni.
egy sorral meg lehet duplázni a tábla tartalmát:

insert into tabla (oszlopnevek) select oszlopnevek from tabla;

Egy átlagos héten négy hétfő és egy péntek van (C) Diabolis

(#5033) Taci válasza bambano (#5032) üzenetére


Taci
addikt

Köszönöm a segítséget. :)

(#5034) Taci válasza Taci (#5033) üzenetére


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.

[ Szerkesztve ]

(#5035) nyunyu válasza Taci (#5034) üzenetére


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...

[ Szerkesztve ]

Hello IT! Have you tried turning it off and on again?

(#5036) Taci válasza nyunyu (#5035) üzenetére


Taci
addikt

Köszönöm a tippet.

Ezt a leírást találtam róla: [link]

Note: Updating a table with indexes takes more time than updating a table without (because the indexes also need an update). So, only create indexes on columns that will be frequently searched against.

Van ilyen lekérdezésem is:
SELECT * FROM table
WHERE channel_id 
IN ('id1','id2','id3','id4') 
AND 
(category LIKE '%category1%' 
OR category LIKE '%category2%'
OR category LIKE '%category3%' 
OR category LIKE '%category4%' 
OR category LIKE '%category5%' 
OR category LIKE '%category6%') 
AND 
(category NOT LIKE '%category7%' 
AND category NOT LIKE '%category8%' 
AND category NOT LIKE '%category9%')
ORDER BY date DESC LIMIT 4

Ez alapján akkor ezeket a mezőket (channel_id, category) is indexelni kellene, mert végülis ugyanolyan gyakran vannak használva?
Látok a link alatt olyat is, hogy lehet indexet mezők kombinációjára is beállítani. A fenti példám alapján hogy lenne jobb? Index külön a mezőkre? Index ezek kombinációjára? Vagy is-is?

És ezt a CREATE INDEX-et csak egyszer kell mezőnként futtatni, és onnan "rendben van"? Azért kérdezem, mert próbálok mindent automatizálni, hogy ne kelljen figyelni rá, ha nem muszáj, és ha ez is olyan, amit többször kell meghívni, akkor erre is figyelnem kell.

Bocsánat a sok kérdésért és értetlenkedésért, csak erről most hallok először, és fontosnak tűnik, nem szeretnék hibázni vele.

Köszönöm.

(#5037) Taci válasza Taci (#5036) üzenetére


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.

[ Szerkesztve ]

(#5038) Taci válasza Taci (#5037) üzenetére


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 (?)

[ Szerkesztve ]

(#5039) martonx válasza Taci (#5034) üzenetére


martonx
veterán

A szolgáltatón múlik, simán lehet, hogy a desktop géped által kibírt 2 milliónak a töredékét se fogja elbírni.
De lehet, hogy a többszörösét :D
Minden csak pénz kérdése...

Én kérek elnézést!

(#5040) Taci válasza Taci (#5038) üzenetére


Taci
addikt

Közben a számosságra is választ találtam: ahány különböző (unique) rekord van a táblában. És ugye hiába van most ~500e rekord, azt a meglévő ~7400-7500-ból sokszorítottam, ezért van az a szám ott. Legalábbis ha jól logikázom.

(#5041) Taci válasza Taci (#5040) üzenetére


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 az EXPLAIN-re. Így most látom, hogy a rows é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 a rows értéke EXPLAIN mellett, 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?

[ Szerkesztve ]

(#5042) nyunyu válasza Taci (#5036) üzenetére


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.

[ Szerkesztve ]

Hello IT! Have you tried turning it off and on again?

(#5043) nyunyu válasza Taci (#5037) üzenetére


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. :))

Hello IT! Have you tried turning it off and on again?

(#5044) nyunyu válasza Taci (#5041) üzenetére


nyunyu
félisten

A probléma leginkább azzal van, hogy szótöredékre próbálsz keresni like '%valami%', emiatt nem nagyon tudja hatékonyan használni a category_id-re tett indexet.

Azért egy próbát megérhet egy (channel_id, category_id) összetett index, hátha segít valamit.

Ha szó elejére keresnél like 'valami%', akkor könnyen meg tudná mondani az indexből, hogy melyik rekordok kellhetnek.

[ Szerkesztve ]

Hello IT! Have you tried turning it off and on again?

(#5045) Taci válasza nyunyu (#5044) üzenetére


Taci
addikt

Köszönöm a sok és részletes választ, illetve a tippeket!

Nem csak a LIKE-os lekérdezésekre ad vissza nagyon lassan választ, de az "alapra" is:
SELECT * FROM table ORDER BY date DESC LIMIT 4
Ezért "nem látom, hogy működne" az indexelés, mert se "alap" lekérdezésnél, se kibővítettnél nem gyorsult semmit. Mit tudok még átnézni, változtatni, ellenőrizni? Lehet, csak a lokál szerver "miatt" ilyen lassú? Mert ha más nem, az alap lekérdezésre már jól kellene (gyors válasszal) működnie.

----------

(A jelenlegi felépítés szerint) muszáj vagyok LIKE-ot használni:
A kategóriákra szűrök így. Mert jelenleg ha category1, category3 és category4-be tartozik egy elem, az most úgy van letárolva, hogy a category mező tartalma a rekordhoz:
"category1,category3,category4"

De a user category1 és category4-re szűr rá, akkor (jelenleg) nem tudom máshogy, mint
AND
(category LIKE '%category1%'
OR category LIKE '%category4%')

Rengeteg féle kategória van (30+), így ez lehet egy elég hosszú sztring is, ezért nem is nagyon tudom, hogyan tudnám máshogy megcsinálni.
De ha van tipped, szívesen veszem.

Vagy esetleg ezt is lehetne IN-nel? Csak nekem úgy kell az eredmény, ha cat1 és cat4-re szűr, akkor mutassa, ha vagy az egyikben, vagy a másikban van (vagy mindkettőben, nyilván). De az IN-nél meg inkább AND az operátor, nem OR.
Tehát a
WHERE category IN ('category1', 'category2')
nem jó eredményt adna vissza, nem?

Köszönöm.

(#5046) tm5 válasza Taci (#5045) üzenetére


tm5
tag

Szerintem le kellene ülni és összeszedni, hogy mik az elvárások és az alapján tervezni egy adatbázist, mert most minden posztodban kiderül valami újabb dolog.

A category oszlopot inkább kiraknám egy külön táblába, mondjuk úgy, hogy ha van egy category szótárod (cat_id, cat_name) akkor lenne egy un. junction táblád (tabla_id, cat_id)
és akkor cat_id alapján gyorsan tudnál keresni. Ez esetben lehetne az IN operátort is használni. Kerüljük a redundanciát ha lehet. Egy Microsoft SQL-es MVP már 15 éve azt írta, hogy egy rendes 3. normálformájú adatbázis sokkal jobban teljesít, mint egy redundanciával teli.

Én amúgy szeretek kompozit indexek helyett külön indexet használni leggyakrabban keresett oszlopokra. Esetleg megpróbálhatod ezt is.

[ Szerkesztve ]

(#5047) nyunyu válasza Taci (#5045) üzenetére


nyunyu
félisten

Jaj, itt már a relációs adatmodell alapjai is hiányoznak.

Ahogy tm5 írja, ki kéne tenni a kategóriákat egy külön táblába, amiben van egy category_id, és egy name mező.
Mivel ez pártíz-száz különböző értéket fog tartalmazni, ezen akár még a lájk is működhetne gyorsan, nem fájna annyira, mint egy nagyonnagy táblán.

Mivel egy termékhez több kategóriát is szeretnél tárolni, illetve egy kategóriába több termék is eshet, így N:M reláció lesz a termék és a kategória között.
Ennek leképezése úgy történik, hogy csinálsz egy termék_kategória táblát, amibe beleteszed a termék azonosítóját, és a kategória azonosítóját.
Ahány kategóriába tartozik, annyiszor veszed fel ide a terméket, mindig a következő kategória azonosítójával.

Lekérdezéskor meg joinolod az id-k mentén a három táblát, valahogy így:

select p.*
from product p
join product_category pc
on pc.product_id = p.id
join category c
on c.id = pc.category_id
where c.name like '%akármi%'
order by p.date desc;

[ Szerkesztve ]

Hello IT! Have you tried turning it off and on again?

(#5048) Taci válasza tm5 (#5046) üzenetére


Taci
addikt

Köszönöm a tanácsot.

Igazából már azt gondoltam, készen vagyok, mehet élesben a weblap (és vele az adatbázis), csak eszembe jutott, megnézem, hogyan viselkedik majd x év adatfelhalmozódása után. És mint kiderült, nem jól...

Szóval tényleg át kell alakítanom, mert így nem lesz jó hosszú távon, és most még bármit csinálhatok vele, bárhogy alakíthatom, mert még csak tesztfázisban van (bár már 1-2 hét múlva küldtem volna bevetésre). Viszont igazad van, ennek tényleg újra neki kell ülni. De sajnos úgy látszik, egyedül én ehhez kevés vagyok. (Így is csodálom, hogy saját erőből (plusz a Ti segítségetek itt, plusz Stackoverflow, plusz W3Schools stb.) fel tudtam ezt építeni, elég sok ez (HTML, CSS, JS, PHP, SQL) egy embernek (nekem legalábbis), úgy, hogy még működjön is).
Szóval talán segítséget kellene kérnem (fizetőst, egy hozzáértőt pár óra szaktanácsadásra), hogy az alapok stabilak legyenek.
Mert hát ahogy írtad is, ilyen csepegtetett infókból nem fog összeállni a kép, és amúgy sem veletek akarnám megoldatni a felmerült problémákat.

Ha esetleg tudtok ilyen szolgáltatást, akár itt, akár privátban jelezzétek, kérlek. (Elképzelésem szerint) óradíjban, megmutatom, hogy működik az oldal, ezt hogyan szolgálja ki jelenleg az adatbázis, ő pedig elmondja, mi és miért nem jó, javítjuk, teszteljük, és örülünk.

Mert logikázhatok én itt egyedül (a Ti segítégetekkel, amit ezúton is köszönök), de ha rossz a logikám, amiből indul az egész, akkor csak az időt húzom a semmire.

Viszont azt amúgy továbbra sem értem, hogy az alap lekérdezéssel miért ilyen piszok lassú, ha egyszer már indexelve is van, és LIKE és kategóriák a közelben sincsenek.

(#5049) nyunyu válasza Taci (#5048) üzenetére


nyunyu
félisten

DB teljesítményhez két dolog szükséges: sok RAM, meg sok, gyors diszk.
Több procimagot is meghálálja, de arra nem annyira érzékeny, mint a kevés memóriára.

Tényleg, nem valami ingyenes DB licenszet használsz, ami 1 magra és 1GB RAMra van korlátozva?
(Pl. Oracle XE, SQL Server Express)

Hello IT! Have you tried turning it off and on again?

(#5050) Taci válasza nyunyu (#5049) üzenetére


Taci
addikt

Azt használom, amit a DesktopServer feltelepített nekem: MariaDB. Az alap beállításon van, nem néztem még rá a konfigurációjára. (De utánanézek, hol és hogyan lehet.)

Amit ajánlottatok, külön táblát létrehozni a kategóriáknak, azt egyelőre nem tudom, hogyan kell megcsinálnom, ennek is utánanézek. Illetve akkor lehet, hogy más mezőket is "ki kell majd szerveznem".

Szóval örülnék egy szaki-ajánlásnak.

Útvonal

Fórumok  »  Szoftverfejlesztés  »  SQL kérdések (kiemelt téma)
Copyright © 2000-2024 PROHARDVER Informatikai Kft.