Hirdetés

2024. május 2., csütörtök

Gyorskeresés

Útvonal

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

Hozzászólások

(#5201) nyunyu válasza Taci (#5199) üzenetére


nyunyu
félisten

Fordítva gondolkozol.

Nem azokat kell megmutatni, amik nem 27-es kategóriájúak, mert akkor a többszörös kategóriából csak azt az egy példányt zárod ki, nem az összeset.

Helyette azokat a termékeket nem szabad megmutatni, amik 27-esek.
Úgy biztosan kizárja a terméket, akárhány kategóriába tartozik is a 27-esen kívül.

SELECT item_id, item_date
FROM items
WHERE
item_id NOT IN (select item_id from items_categories where
category_id in (27))
ORDER BY item_date ASC LIMIT 4

[ Szerkesztve ]

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

(#5202) Taci válasza Taci (#5199) üzenetére


Taci
addikt

Saját kútfőből erre jutottam: DB Fiddle

Van esetleg valakinek jobb/másabb ötlete? Valós adatbázison még csak most fogom kipróbálni, nem tudom, mennyire lehet gyors/lassú.

@nyunyu: Most látom csak, hogy írtál, máris nézem, köszönöm.
Oh, valóban, pont ellenkezőleg gondolkodtam... Köszönöm az irányba állítást! :)

[ Szerkesztve ]

(#5203) nyunyu válasza Taci (#5202) üzenetére


nyunyu
félisten

Ugyanezt benéztem nemrég melóban.

Még szerencse, hogy a tesztelők is átnézték a GDPR törlendő szerződések listáját, és kiszúrták, hogy a left join tiltolista + where tiltolista.id is not null átengedte azokat a szerződéseket, ahol csak az egyik ügyfél volt tilitólistás, másik nem.
Írhattam át a queryt where ügyfél not in (select id from tiltolista)-ra.

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

(#5204) Taci válasza nyunyu (#5203) üzenetére


Taci
addikt

Ezért is fontos a QA. :) Meg a lomtár. :D

Én most egy kicsit értetlenül is álltam a dolog előtt, mert egy ilyen hibát észrevettem volna ennyi idő alatt (már kerestem egy ideje, nem egyből ide jöttem segítséget kérni).

Aztán rájöttem, hogy egy régi lekérdezést mutattam példának, azt átalakítva a problémához - viszont a problémás lekérdezés nem ez volt...

Szóval most átírtam a példához újra: DB Fiddle

De hátha ez is egy teljesen egyértelmű hiba részemről csak, hogy itt nem úgy működik, ahogy szeretném.

Ránéznél, kérlek?

[ Szerkesztve ]

(#5205) nyunyu válasza Taci (#5204) üzenetére


nyunyu
félisten

Ugyanúgy, where alá megy a szűrő alquery:
SELECT f.item_id, f.item_date
FROM
(SELECT item_id, item_date
FROM items
ORDER BY item_date ASC LIMIT 1000) AS f
INNER JOIN items_categories AS fic
ON f.item_id=fic.item_id
WHERE f.item_id not in (select t.item_id
from items_categories t
where t.category_id IN (27))

GROUP BY f.item_id, f.item_date
ORDER BY f.item_date ASC LIMIT 4

Tehát a termék-kategória párosokból leválogatod azokat a termékeket, akik a nemszeretem kategóriában vannak, és ezzel szűröd az eredeti terméklistát.

[ Szerkesztve ]

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

(#5206) martonx válasza Taci (#5199) üzenetére


martonx
veterán

Szerintem hibás a feltétel vizsgálatod.
Tippre ez adja az elvárt adatokat:

WHERE
item_id not IN (select item_id from items_categories where
category_id in (27))

ah, és rögtön válaszoltam, nem görgettem le, látom nyunyu is ugyanerre jutott :R

[ Szerkesztve ]

Én kérek elnézést!

(#5207) martonx válasza Sokimm (#5200) üzenetére


martonx
veterán

Szvsz egy access makró programozás probléma, aminek a nyelve a VBA, nem pedig SQL probléma. Vagy pedig még a kérdés felvetést sem sikerült megértenem.
Ezer éve volt, hogy access-t VBA-val programoztam, egy porickám se kívánja feleleveníteni.

Én kérek elnézést!

(#5208) Taci válasza nyunyu (#5205) üzenetére


Taci
addikt

Köszönöm szépen ismét, így már valóban úgy működik, ahogy szeretném. :)
Magamtól ezt csak nagyon sokára oldottam volna meg (ha egyáltalán...). Pedig így végig gondolva szép nyugodtan, teljesen logikus.

Köszönöm!

@martonx: Neked is. :)

(#5209) Sokimm válasza martonx (#5207) üzenetére


Sokimm
senior tag

SELECT gyerkekNevei
FROM szemelyekadatai_tabla
WHERE *
INSERT INTO Table3 firstcolumns

Ez átmásolja a gyerekek neveit a 3. táblázatba vajon?

[ Szerkesztve ]

(#5210) bambano válasza Sokimm (#5209) üzenetére


bambano
titán

insert into table3 (gyereknevei) select gyereknevei from szemelyekadatai_tabla;

de redundanciát pakolni az adatbázisba az elég gyors menetjegy a pokolba :)

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

(#5211) Ispy válasza Sokimm (#5200) üzenetére


Ispy
veterán

A kérdés, hogy minek a 3. tábla? Nem lehet, hogy az csak egy lekérdezés? Vagy minek még 1x letárolni mindent megint? Ez így nem túl adatbázisos megoldás.

Először azt kéne definiálni, hogy pontosan mire akarod azt a táblát használni.

[ Szerkesztve ]

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

(#5212) nyunyu válasza Sokimm (#5200) üzenetére


nyunyu
félisten

Nem teljesen értem, mire való a második táblád.

Ha ebben csak a lehetséges táborozási opciók vannak felsorolva, és a harmadik táblába viszed fel a beérkezéskor, hogy melyik gyerek melyik opciókat kéri, akkor a harmadik táblába csak a gyerek nevét (vagy elsődleges azonosítóját/kulcsát), és az opció azonosítóját kell letárolnod.

Ha a második táblában előre le vannak tárolva, hogy melyik gyerek mit kért (gyerekneve/azonosítója, opció párosként), akkor a harmadik tábla helyett kellene egy lekérdezés vagy nézet, ami ebből egy mátrixot rajzol.

valahogy így:
select nev, vega, reggeli, ebed, vacsora, szamtech, lovas, uszas
from (
select x.nev,
max(x.vega) vega,
max(x.reggeli) reggeli,
max(x.ebed) ebed,
max(x.vacsora) vacsora,
max(x.szamtech) szamtech,
max(x.lovas) lovas,
max(x.uszas) uszas,
from (
select gy.nev,
case when o.opcio = 'Vega' then 'I' else '' end vega,
case when o.opcio = 'Reggeli' then 'I' else '' end reggeli,
case when o.opcio = 'Ebéd' then 'I' else '' end ebed,
case when o.opcio = 'Vacsora' then 'I' else '' end vacsora,
case when o.opcio = 'Számítástechnika' then 'I' else '' end szamtech,
case when o.opcio = 'Lovas' then 'I' else '' end lovas,
case when o.opcio = 'Úszás' then 'I' else '' end uszas,
from gyerekek gy
join opciok o
on o.gyerek_id = gy.id) x --vagy o.nev = gy.nev, ha nevet tárolsz
group by x.nev);

Ennek az eredménye egy ilyen táblázat lesz:
NEV VEGA REGGELI EBED VACSORA SZAMTECH LOVAS USZAS
Kiss Péter I I I I
Nagy Anett I
Török Flóra I I I

(Bocs, nem nagyon vágom az Accesst, de elvileg szabvány SQL-ben is meg lehet feléje fogalmazni a kéréseket.)

[ Szerkesztve ]

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

(#5213) nyunyu válasza nyunyu (#5212) üzenetére


nyunyu
félisten

Elvileg meg lehetne írni PIVOT() függvénnyel is, de azt nem minden adatbáziskezelő ismeri, meg szerintem elég átláthatatlan a szintaxisa.

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

(#5214) Apollo17hu


Apollo17hu
őstag

Sziasztok!

Kumulálás témában kérem a segítségetek. Pozitív és negatív egész számaim vannak egy mezőben. Egy másik mezőben azonosító szerepel, a rekordok e mentén vannak rendezve.
Az a feladat, hogy a számokat kumuláljuk, de a kumulált érték nem lehet magasabb nullánál. Tehát ha az aggregálás "átfordulna" a pozitív tartományba, akkor ott 0-nak kell szerepelnie.

Így néz ki a modell, amiben a 3. oszlopot kellene létrehoznom:

ID ERTEK KORR_ERTEK
A -2 -2
B -5 -7
C -1 -8
D 3 -5
E 10 0
F -7 -7
G -4 -11
H 20 0
I -1 -1
J -3 -4

Sajnos sqlfiddle hibát dob, ezzel próbálkoztam:

CREATE TABLE proba (
    id varchar2(10),
    ertek number
)
;
INSERT INTO proba
    ([id], [ertek])
VALUES
    ('A',-2),
    ('B',-5),
    ('C',-1),
    ('D',3),
    ('E',10),
    ('F',-7),
    ('G',-4),
    ('H',20),
    ('I',-1),
    ('J',-3)
;

Milyen módon lehetne kiszámolni a KORR_ERTEK mezőt?

Maga a kumulálás ezzel működik, de a nullával való korrigálásra nem jöttem rá:
SUM(ertek) OVER(ORDER BY id)

(#5215) nyunyu válasza Apollo17hu (#5214) üzenetére


nyunyu
félisten

Mint az egyszeri matekpélda, ahol az első megállóban felszáll 2 ember a buszra, másodiknál leszáll 5, akkor hány embernek kell felszállnia a harmadiknál, hogy senki ne legyen a buszon?

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

(#5216) Apollo17hu válasza nyunyu (#5215) üzenetére


Apollo17hu
őstag

Igen, úgy! Próbáltam keresgélni a neten, és mindenhol rekurzív sql-kódokra bukkantam, de nagyon nem sikerül összerakni, hogy működjön.

(#5217) pch válasza Apollo17hu (#5214) üzenetére


pch
aktív tag

Ha csak annyi hogyha nagyobb mint 0 akkor legyen nulla akkor arra ott az if
IF(eredmeny>0,0,eredmény)

http://sb-soft.hu - "A" számlázó

(#5218) Sokimm válasza nyunyu (#5212) üzenetére


Sokimm
senior tag

A gyerekekkel való példa csak példa, az adatok "értelmezéséhez" kellett, bár lehet elég bénán fogalmaztam, ettől függetlenül siekrült a művelet, köszönöm a segítséget (mindenkinek!).
(hogy válaszoljak is: Azért kell a 2 táblából egy 3.at csinálni, hogy merge-öljem az összes adatot egybe, de "logika" alapján. Az első 2 tábla majd megy a levesbe, a 3. lesz használva csak a jövőben)
Ezért nem elég csak egy lekérdezés, fontos a friss táblába mozgás.

Most viszont a WHERE résszel szenvedek (megint szerintem szintaktika), mert mindig kér kezdő paramétert SQL futtatásakor.

Most nem írok béna példát, csak a szintaktikát kérném segítsetek megérteni.
(Nem tudom mikor használunk gyémánt operátort, vagy [...] ilyet, meg a sima zárójeleit se értem a Microfos-nak. :)) )
A hibám az, hogy a WHERE végén lévő Zenetagozatosok.NEV mindig kér kezdő paramétert SQL futtatásakor, nem képes a két tábla azonos oszlopát összehasonlítani automatán. :(
UPDATE ...
SET ...
WHERE  (((ÖsszesGyerekTabla.NEV)=([Zenetagozatosok].[NEV])));

(#5219) Ispy válasza Sokimm (#5218) üzenetére


Ispy
veterán

Hun van a selectből a join?

Ezt a where-es megoldást ne erőltesd, én nem legalább is nem szoktam:

update x set mező=...
from x
inner join y on x.mező=y.mező

Így csak azokat fogja frissíteni, ahol x-ben és y-ban is megtalálható a kapcsolat alapján a rekord.

Ez mondjuk nem access, hanem ms sql, már rég nem accesseztem, szerencsére, de hátha megeszi.

Kicsit furán kezeled az accesst, mint valami excel táblát. :D Nem mint egy relációs adatbázist.

A gyémánt operátor egy kapcsos zárójel (leánykori nevén), ebben az esetben gondolom nincsen from és paraméterként értelemzi az access, egyébként ms sql-ben így illik a mezőkre hivatkozni, mert egyébként ha a mező neve egy operátor is, akkor a fordító nem tudja mit akarsz és hibára fut. Vagy ha gyilkos modon szóköz van a mező nevében, akkor is megpusztul. Ilyenkor a kapcsos zárójel közötti részt mezőként értelmezi.

Egyébként valami ilyesmi is lehet a megoldás:

update x set mező=....
from x, y
where (x.mező=y.mező)

Csak én rosszul vagyok ettől a sytanxistól.

[ Szerkesztve ]

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

(#5220) Apollo17hu válasza pch (#5217) üzenetére


Apollo17hu
őstag

nem csak annyi :N

(#5221) nyunyu válasza Ispy (#5219) üzenetére


nyunyu
félisten

UPDATEben JOIN???

Nagyon nem szabványos, helyette van a MERGE parancs.

MERGE táblanév u
USING (joinolandó alquery) x
ON (x.valami = u.valami)
WHEN MATCHED UPDATE SET u.akármi = x. akármi;

[ Szerkesztve ]

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

(#5222) Ispy válasza nyunyu (#5221) üzenetére


Ispy
veterán

Microsoft....egyébként hasznos. :D

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

(#5223) nyunyu válasza Ispy (#5222) üzenetére


nyunyu
félisten

Tudom, Teradata huszonévvel ezelőtti szintaxisát emelték be az SQL Server 2008-ba, ami sosem volt szabványos.

Mondjuk a Teradatának volt egy olyan hasznos fícsöre, hogy csak a sikeresen illesztett sorokon updatelte a cél táblát, míg ha Oraclenek valami ilyesmit írtál:
UPDATE tábla1 u
SET u.valami = (select valami from másiktábla a where a.id=u.id);

Akkor a nem illeszkedő sorokat is felülvágta NULL-lal :W
(Nem emlékszem pontosan az elszabott Oracle szintaxisra, helyette mindig MERGEet írtam.)

[ Szerkesztve ]

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

(#5224) Apollo17hu válasza Apollo17hu (#5214) üzenetére


Apollo17hu
őstag

Többé-kevésbé sikerült összeraknom. Álljon itt az utókornak:

WITH t AS
 (SELECT t.id
        ,t.ertek
        ,row_number() over(ORDER BY t.id) AS seqnum
  FROM   (SELECT 'A' AS "ID",-2 AS "ERTEK" FROM dual
          UNION ALL
          SELECT 'B',-5 FROM dual
          UNION ALL
          SELECT 'C',-1 FROM dual
          UNION ALL
          SELECT 'D', 3 FROM dual
          UNION ALL
          SELECT 'E',10 FROM dual
          UNION ALL
          SELECT 'F',-7 FROM dual
          UNION ALL
          SELECT 'G',-4 FROM dual
          UNION ALL
          SELECT 'H',20 FROM dual
          UNION ALL
          SELECT 'I',-1 FROM dual
          UNION ALL
          SELECT 'J',-3 FROM dual) t),
cte(id,ertek,runningsum,seqnum) AS
 (SELECT ID
        ,ertek
        ,(CASE
           WHEN ertek > 0 THEN
            0
           ELSE
            ertek
         END) AS runningsum
        ,seqnum
  FROM   t
  WHERE  t.seqnum = 1
  UNION ALL
  SELECT cte.id
        ,t.ertek
        ,(CASE
           WHEN t.ertek + cte.runningsum > 0 THEN
            0
           ELSE
            t.ertek + cte.runningsum
         END) AS runningsum
        ,t.seqnum
  FROM   cte
  JOIN   t
  ON     t.seqnum = cte.seqnum + 1
         /*AND t.id = cte.id*/)
SELECT cte.ertek, cte.runningsum AS korr_ertek
FROM   cte
ORDER  BY seqnum

(#5225) Ispy válasza nyunyu (#5223) üzenetére


Ispy
veterán

2008-tól van merge ms-nél is, de én csak az utóbbi időben kezdtem használni és csak tábla függvényben, annyira megszoktam már az update-et.

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

(#5226) Ispy válasza Apollo17hu (#5224) üzenetére


Ispy
veterán

Szegény utókor. ;] :P

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

(#5227) Sokimm válasza Ispy (#5219) üzenetére


Sokimm
senior tag

UPDATE new_table
SET new_table.Parameter1=old_table.Parameter1,
FROM new_table
INNER JOIN old_table ON old_table.AzonosParameter = new_table.AzonosParameter
;

Az uj tablat szeretném frissiteni, amiben beállítódik a Parameter1 (régiből az újba), az (FROM) új táblából..?
Egyesítsük az old table-t ha a régi és új tábla azonos paramétere egyezik.
Ez így nem megy. :D
Megint mit rontok el?
Most jön a merge próba. :)

(#5228) nyunyu válasza Apollo17hu (#5214) üzenetére


nyunyu
félisten

Az a baj, hogy az előző lépésben számolt értékre van szükséged a következő kiszámolásához, és nem szimplán szummázod a korábbi értékeket.

Így vagy rekurzívan számolod ki, vagy ciklust írsz rá.

Ezekre nem nagyon van szabvány szintaxis, kb. minden DBnek más megoldása van rá.

Oracle alatt valahogy így nézne ki a ciklusos megoldás:
DECLARE
v_id varchar2(10);
v_ertek number;
v_korr_ertek number := 0;
CURSOR c is
SELECT id, ertek
FROM proba
ORDER BY id;
BEGIN
OPEN c;
LOOP
FETCH c INTO v_id, v_ertek;
EXIT WHEN c%notfound;
v_korr_ertek := CASE WHEN v_korr_ertek + v_ertek > 0
THEN 0
ELSE v_korr_ertek + v_ertek
END;
dbms_output.put_line(v_id || ',' || v_ertek || ',' || v_korr_ertek);
/*
UPDATE proba
SET korr_ertek = v_korr_ertek
WHERE id = v_id;
*/
END LOOP;
CLOSE c;
END;

Deklarálsz egy kurzort, amiben azonosító szerint növekvő sorrendben jönnek a rekordok, aztán azon egyesével végig mész, kiszámolva az aktuális korrigált értéket.

[ Szerkesztve ]

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

(#5229) Ispy válasza Sokimm (#5227) üzenetére


Ispy
veterán

Mi a hibaüzenet? Az azért sokat tud segíteni, egyébként. :)

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

(#5230) Sokimm válasza Ispy (#5229) üzenetére


Sokimm
senior tag

syntax error :D Valahogy lehet gazdagabb hibaüzit olvastatni az MS-el?

(#5231) nyunyu válasza Sokimm (#5227) üzenetére


nyunyu
félisten

Ha nagyon gonosz akarnék lenni, akkor:
UPDATE new_table
SET Parameter1=old_table.Parameter1
WHERE old_table.AzonosParameter = new_table.AzonosParameter;

(30+ évvel ezelőtti Teradata szintaxis, még a FROM clause bevezetése előttről.
Kellett nekem ilyenekre SQL parsert írnom adattárház gyakornok koromban. :W)

Ha meg nem akarnék az lenni, akkor:
MERGE new_table u
USING old_table o
ON (u.AzonosParameter = o.AzonosParameter)
WHEN MATCHED THEN UPDATE
SET Parameter1=o.Parameter1;

[ Szerkesztve ]

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

(#5232) Ispy válasza Sokimm (#5230) üzenetére


Ispy
veterán

Hát passzolom akkor, én amikor accesst használtam akkor is ms sql adatbázis volt mögötte, ilyen hackeket meg soha nem csináltam kézzel, csak VBA-ból max. A beépített varázsló szarokat meg soha nem használtam, mert borzalmasak.

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

(#5233) Ispy válasza Sokimm (#5227) üzenetére


Ispy
veterán

Áhá, megvan, van egy fölösleges vessző a SET sor végén. :D

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

(#5234) nyunyu válasza Apollo17hu (#5224) üzenetére


nyunyu
félisten

Tényleg, a CTE szabványosításának az is volt a célja, hogy az addigi, DB függő szintaxis helyett könnyebben lehessen rekurzív queryket írni.

De sosem szerettem rekurzív kódot írni, mert nagyon könnyen beláthatatlan tud lenni.

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

(#5235) sztanozs válasza Sokimm (#5200) üzenetére


sztanozs
veterán

Nem biztos, hogy értem, hogy mit szeretnél...
Egyrészt a tűblákat érdemesebb volna ID-val csinálni (mert mi van, ha van két ugyanolyan nevű Kis Péter), de ha eddig nem kézzel volt szinkronizálva a tábla, hanem valami automatizmussal, akkor működhet a mezők "összekötése" utólag is.
Amúgy a harmadik tábla csak egy query lenne, vagy ott is tárolnál valami plusz infót?
Valahogy így raknám össze, ha sokat nem akarnék vacakolni:

De rendesen, Id-kkal valahogy így nézne ki:

[ Szerkesztve ]

JOGI NYILATKOZAT: A bejegyzéseim és hozzászólásaim a személyes véleményemet tükrözik; ezek nem tekinthetők a munkáltatóm hivatalos állásfoglalásának...

(#5236) nyunyu válasza Apollo17hu (#5224) üzenetére


nyunyu
félisten

Hmm, jobban megnéztem ezt a részt:
with cte(id,ertek,runningsum,seqnum) as
(select 0.szint
union
select n+1. szint)
select ... from cte;

Ez pont ugyanúgy néz ki, mint amit a Teradata 13 tutorialokban láttam anno.
Ezek szerint az már szabványosított rekurziós szintaxist használhatott?

Mondjuk a Teradata mindig hamarabb implementálta az új SQL szabványokat, mint az Oracle :D

[ Szerkesztve ]

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

(#5237) Apollo17hu válasza nyunyu (#5236) üzenetére


Apollo17hu
őstag

Hat, azt nem tudom, hogy mi hogyan irodhatott, de abban nagyon igazad van, hogyha az ember nem gyakorlott benne, akkor elegge necces a hasznalata. Egy kivalasztott peldara meg nehany masodperc alatt lefutott a kodom, de szazmillios rekordszamom van, ugyhogy inkabb elengedem a rekurziv temat. Igazabol csak egy szep megoldast kerestem, mert mas modon kozel 100%-os pontossaggal meg tudom hatarozni az ertekeket - es szerencsere ez most eleg.

(#5238) nyunyu válasza Apollo17hu (#5237) üzenetére


nyunyu
félisten

Rekurzió az matematikalag elegáns, gyakorlatban meg nagyon nem praktikus, akármelyik programnyelvet nézem.

[ Szerkesztve ]

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

(#5239) sztanozs válasza nyunyu (#5238) üzenetére


sztanozs
veterán

Inkább általában a futtatókörnyezet implementációja/limitációi miatt nem praktikus.

JOGI NYILATKOZAT: A bejegyzéseim és hozzászólásaim a személyes véleményemet tükrözik; ezek nem tekinthetők a munkáltatóm hivatalos állásfoglalásának...

(#5240) Taci


Taci
addikt

Lenne egy egyelőre csak elméleti kérdésem.

Ha jól tudom, valahogy összefüggésben van az indexelt mezők száma, illetve az adatbázisba való írás sebessége: minél több mező van indexelve, talán annál több idő a rekordok adatbázisba való írása. Ezt jól tudom?

Azt szeretném kideríteni, van-e olyan "váltópont", ahonnan már annyira belassulna az adatbázisba való írás, hogy nem érné meg az indexelés használata.

A kérdés háttere:
5 percenkénti kb. 100-400 új rekorddal számolva (még ezt nem tudom, mennyi lehet valósan, de itt körül, szóval legyen ennyi a példa kedvéért) megéri-e full text search-re átállnom a gyorsabb keresés kedvéért?
Ehhez ugye be kell állítanom full text indexet azokra a mezőkre, amiben keresni akarok. Pl.:
ALTER TABLE feed ADD FULLTEXT(title)
ALTER TABLE feed ADD FULLTEXT(description)

Viszont mivel elég sok rekord kerül a táblába folyamatosan, azt szeretném kideríteni, hogy emiatt (és a többi) indexelés miatt lehet-e gond később (bármikor, akármikor) a teljesítménnyel, esetleg belassulhat-e annyira az adatbázisba való írás, hogy az 5 percenkénti cron job "túl sűrű" lesz, mert ennyi idő alatt nem végez az új rekordok tárolásával?

Lehet, hogy teljesen alaptalan a "félelmem", de ez a kérdés bennem van már egy ideje, de még csak most jutottam a keresés rendbe tételéhez.

Jelenleg jobb híján a LIKE %%-os keresést használom, kb. 1 mp a lekérdezési ideje egy 300e-res táblánál, szóval nem vészes, úgyhogy az sem tragédia, ha ez marad egy ideig. Plusz a full text search-keresés amúgy sem olyan egyszerű, mint jó lenne.

(#5241) martonx válasza Taci (#5240) üzenetére


martonx
veterán

Szerintem megválaszoltad magadnak. A hídon majd ráérsz akkor átmenni, amikor odaértél.
Egyébként is van sok lehetőséged, én a helyedben, amikor a mostani megoldás elkezd kevés lenni (ha lesz ilyen), akkor első körben megpróbálnám a felvázolt full text search-öt SQL oldalon megvalósítani.
De ennél is jobb tud lenni, ha beüzemelsz egy ElasticSearch szervert az SQL-ed fölé, és ez szolgálja ki a szöveges kereséseket. Bár ez elég overkill.

Én kérek elnézést!

(#5242) nyunyu válasza Taci (#5240) üzenetére


nyunyu
félisten

Azt neked kell végiggondolni, hogy a táblád legszélesebb oszlopát indexelni akarod-e.
Ha igen, az (közel) megduplázza a tábla helyigényét, de legalább minden beszúrás, törlés művelet sokkal lassabb lesz, hiszen az indexet is karban kell tartania.

Kérdés, hogy ez megéri-e azt, hogy néha-néha like '%%'-kal akarj benne keresni.
De mivel egy sokszázezer soros táblára tett többezer karakter széles index sem fog beleférni a memóriába, így szerintem tökmindegy, hogy az eredeti táblán megy a full table scan, vagy a nem sokkal kisebb indexet kell végigolvasnia először, és csak utána éri el a táblát.
Gyors az nem lesz...

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

(#5243) nyunyu válasza martonx (#5241) üzenetére


nyunyu
félisten

ElasticSearchtől azóta kapok sikítófrászt, mióta kedvenc adóhatóságunk olyat szeretett volna az adószámla egyenlegek tárolására + napi újraszámolására, mert az menő, passzol a mikroszerviz architektúrába, és jól skálázható. (meg ingyenes(?) a licensze, tehát többet lehetett volna a projektből khm. megtartani)

Szerencsére főnökömnek sikerült megértetnie velük, hogy nagy mennyiségű, jól struktúrált adat kezelésére rendes RDBMS való, meg arra találnak hozzáértő szakembereket is, sok tapasztalattal.

Aztán a projekt végén, amikor csak a mi modulunk készült el határidőre (emiatt nem kellett meneszteni a projektért felelős álomtitkárt, meg az illetékes vezérőrnagyokat a sóhivatalból), akkor jól le lettünk szúrva, hogy de hát az architektúra szerint semmi SQL nem lehet a kódban, hol van az ElasticSearch, így nem veszik át.

Közben a projektmenedzseri divatlapokban olvasott menő három-négybetűs buzzwordökből összeollózott szent architektúrát szolgaian követő többi fejlesztőcsapat 2 év alatt 2 év késést hozott össze :DDD

[ Szerkesztve ]

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

(#5244) martonx válasza nyunyu (#5243) üzenetére


martonx
veterán

"az adószámla egyenlegek tárolására + napi újraszámolására" - attól még, hogy valakik hülyék, szöveges keresésre igenis kiváló (sőt erre lett kitalálva) az ElasticSearch.
Az állami projekteket meg inkább nem kommentelném :D

Én kérek elnézést!

(#5245) Taci


Taci
addikt

Köszönöm szépen a magyarázatot. :)

(#5246) Taci


Taci
addikt

Az indexekkel kapcsolatban annyit hadd kérdezzek már még, hogy kell-e őket valahogy "kezelni, karbantartani"? Van nekem bármi dolgom velük a létrehozásukon kívül? Mert elsőre azt gondolnám, hogy minden más már a rendszer dolga lenne, de azért inkább rákérdezek, hátha figyelnem kell (majd idővel) valamire, bármire.

Első körben ezt találtam: [link]

Ezt úgy tudom elképzelni, hogy (maintenance módban) az indexeket újraépítem majd, ha szükség lesz rá (törlés, és újra létrehozás), ahogy írja is.

(#5247) martonx válasza Taci (#5246) üzenetére


martonx
veterán

1. Ember csináld már meg amit akarsz, ne tökölődj a mi lesz majd 50 év múlva ha nyerek a lottón szintű problémákon.
2. amit linkeltél MS SQL-re vonatkozik, tudtommal te valami játszós DB-t használsz (MariaDB vagy MySQL vagy valami ilyesmit).
3. Egyébként igen, van amikor karban kell tartani az indexeket, nyugodj meg, te sose futsz ilyen esetbe bele, vagy ha igen, addigra már rég milliárdos leszel, és lesz DB admin embered, aki majd elszórakozik az ilyen problémával.

Én kérek elnézést!

(#5248) nyunyu válasza Taci (#5246) üzenetére


nyunyu
félisten

Indexet csak a leggyakrabban keresett/joinolt oszlopokra érdemes tenni.
Ha a hébe-hóba kérdezett feltételeket is indexeled, azzal többet ártasz, mint használsz, mert az új rekordok beszúrása, illetve régiek törlése is lassul minden egyes plusz indexszel.

Törlés+index létrehozás, újraépítés max akkor segít, ha nagyon sok rekordot töröltél a táblából, és emiatt lyukas lesz az index, és nem működik optimálisan.
De ez megint a többmillió soros táblák problémája, alatta jellemzően nem nyersz sokat azzal, hogy újraépíted.

Szélsőséges példa: van egy millió soros táblád, ennek az indexe is millió rekordot tartalmaz.
Kitörölsz a táblából 900k rekordot, ekkor az index mérete nem változik, továbbra is 1m helyet foglal, lesz benne 900k lyuk.
Újraépítés után az index mérete lecsökken a maradék 100k-ra, így 10x gyorsabban lehet majd végigmenni rajta, mint újraépítés nélkül.
(B-fáknál log2(10) a gyorsulás?)

[ Szerkesztve ]

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

(#5249) Taci válasza nyunyu (#5248) üzenetére


Taci
addikt

Köszönöm a magyarázatot, így már világos. :)
@martonx: Neked is.
Amúgy csinálom, folyamatosan. Azért jött fel ez a legutóbbi két kérdés, mert anno amikor nagyon-nagyon elakadtam, akkor találtam egy srácot, aki órabérben ránézett az egészre, ő tett jó pár javaslatot és kommentet, és ezeket én feljegyeztem (a to-do listámba). Vele azóta sajnos nem tudtam beszélni, a kérdések pedig ott voltak nyitott pontként, és most, hogy végre a keresés részét is rendbe raktam (és a hozzá kapcsolódó pontok kikerültek így a listából), utamba került ez a két kérdés is, ezért kértem tanácsot velük kapcsolatban. Mert ha olyan dolgok lettek volna, amikkel előre számolnom kell (és a kódokat hozzájuk igazítanom), akkor még indulás előtt történjen.
Köszönöm a türelmeteket és a segítségeteket.

(#5250) crmtanulo


crmtanulo
friss újonc

Hali,

szeretném megtanulni a CRM programozást, de eddig nem találtam ilyen oktatási anyagot, tudnátok segíteni ebben?

Útvonal

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