Hirdetés
Új hozzászólás Aktív témák
-
válasz
kw3v865
#5975
üzenetére
Egyrészt lehet tranzakcióval szeparálni.
Másrészt csinálhatsz verziózott adatokat.
Hozzáadsz egy verzió mezőt, minden adatbetöltésnél egy új verziószámot írsz bele, és a tranzakció végén inkrementálod az aktuális verzió mezőt.Tudomásom szerint a postgresnek nincs in-memory táblája, ramdiszkre lehet tablespace-t rakni.
Vagy erre a táblára használhatsz másik adatbáziskezelőt, ami erre van optimalizálva.
-
Magnat
veterán
válasz
kw3v865
#5975
üzenetére
Szia,
nem ismerem a PostgreSQL-t, de igent tippelnék, sőt, mivel az insert elvileg row exclusive lockol (tehát nem a teljes táblát) az is lehet, h a rekordok fele már be lesz szúrva amikor a fv lefut, a többi meg még nem ...
BEGIN;
TRUNCATE TABLE tábla;
LOCK TABLE tábla IN EXCLUSIVE MODE;
INSERT INTO tábla SELECT * FROM másik_tábla WHERE feltétel;
COMMIT;Én vhogy így csinálnám, nyilván ha a fv éppen akkor fut rá amikor ez történik, akkor egy picit várni fog. (Már ha fontos, h üres táblára vagy az insert közepén ne fusson le)
Illetve a truncate elvileg gyorsabb mint a delete, szóval amiatt is így használnám.
-
kw3v865
senior tag
válasz
kw3v865
#5681
üzenetére
Na, most mégiscsak megakadtam a logikai replikációnál: triggert (vagy rule-t, mindegy) szeretnék rakni arra a táblára, ahová replikálódik az eredeti tábla tartalma. Egyelőre nem tudtam működésre bírni. Hibát nem dob, csak egyszerűen nem csinál semmit.
Egy tök egyszerű triggerről van szó a példa kedvéért: egy másik táblába insertál valamit, ha meghívódik (insertre van ráállítva).CREATE OR REPLACE FUNCTION valami()RETURNS TRIGGERLANGUAGE PLPGSQLAS $$BEGININSERT INTO t2 (c) VALUES ('xyz');RETURN NEW;END;$$CREATE TRIGGER trgAFTER INSERT ON t1FOR EACH ROWEXECUTE PROCEDURE valami()
Azt találtam, hogy külön engedélyezni kell ilyen esetben a triggert:ALTER TABLE t1 ENABLE ALWAYS TRIGGER trig;
Ez megtörtént, de hiába.Ha nem az "eredeti", hanem a replikátum táblába insert-álok, akkor meghívódik. Viszont én azt szeretném, hogy akkor is működjön, ha az eredeti táblába insert-álok valamit. Rule-lal sem megy.
Vajon mi lehet ennek az oka? -
nyunyu
félisten
válasz
kw3v865
#5018
üzenetére
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

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.
-
nyunyu
félisten
válasz
kw3v865
#5016
üzenetére
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. -
nyunyu
félisten
-
-
kojakhu
újonc
válasz
kw3v865
#4995
üzenetére
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... -
válasz
kw3v865
#4995
üzenetére
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á.
-
nyunyu
félisten
válasz
kw3v865
#4997
üzenetére
Nem teljesen értem, hogy mit is szeretnél igazából.
Leválogatni a legsűrűbb időbélyeg környékeket?
Listázni az időbélyegeket, és a tőlük max 1 percre lévő logbejegyzéseket?Utóbbira valami ilyesmit tudnék elképzelni:
SELECT *
FROM (
SELECT a.date min_date,
row_number() over (group by a.date order by b.date) rn,
b.*
FROM table a
JOIN table b
ON b.date >= a.date
AND b.date <= a.date + interval '1' minute)
ORDER BY min_date, rn; -
nyunyu
félisten
válasz
kw3v865
#4995
üzenetére
Nem lenne egyszerűbb az időbélyegek különbsége alapján számolni?
SQL szabvány szerint mint a dátum, mind az időbélyeg típusok kivonhatóak egymásból és akkor kapsz egy időintervallumot.
Vagy dátum+időintervallum=dátum, időbélyeg+időintervallum=időbélyeg!Én legalábbis úgy nézném meg, hogy mi a legsűrűbben logolt környék, hogy önmagával összejoinolnám a táblát, hogy a második rekord időbélyege nagyobb legyen, mint az elsőé, és a különbségük egy percen belül legyen, aztán ezt a halmazt group by-olnám az első időbélyegre, és megszámolni, hány második tartozik hozzá.
valami ilyesmire gondoltam:
SELECT y.date, y.cnt
FROM (
SELECT x.date, count(x.date2) cnt
FROM (
SELECT a.date, b.date as date2
FROM table a
JOIN table b
ON b.date > a.date
AND b.date < a.date + interval '1' minute) x
GROUP BY x.date) y
ORDER BY y.cnt desc;Itt az erős join miatt csak azokat az dátumokat/időbélyegeket fogod visszakapni, ahol egy percen belül volt legalább egy másik bejegyzés.
Magányos, kósza bejegyzéseket nem! (mondjuk a b.date >= a.date feltétellel azokat is figyelembe lehetne venni.) -
válasz
kw3v865
#4910
üzenetére
Ez már operációkutatás, nem adatbázis kérdés...
tegyük fel a következőt:
1 | 2 | 10 | 20
2 | 2 | 10 | 30
3 | 2 | 10 | 40
4 | 2 | 20 | 30
5 | 2 | 20 | 40
6 | 2 | 20 | 50
7 | 2 | 30 | 40
8 | 2 | 30 | 50
9 | 2 | 30 | 60
Ezzel a forrással milyen range-eket hozol létre és melyik melyikbe tartozna? -
-
-
-
-
nyunyu
félisten
válasz
kw3v865
#4617
üzenetére
Ha az a cél, hogy egy külső alkalmazás paraméterezetten hívjon egy eljárást/függvényt, akkor nem tudod refcursorral visszaadni a szűrt halmazt?
Legalábbis mi Oracle 11g alapon így szoktuk visszaadni az adatokat:
procedure get_order_status(p_group_id number, p_posting_id number, p_id number, p_order_num varchar2, c out sys_refcursor) is
begin
open c for
select
i.group_id,
i.posting_id,
i.id,
i.order_num,
o.status as status,
to_char(o.status_dt,'yyyy-mm-dd hh24:mi:ss') as status_ts
from input i
left join s_order o
on o.order_num= i.order_num
where i.id = p_id
or i.group_id = p_group_id
or i.posting_id = p_posting_id
or i.order_num = p_order_num;
end;Aztán Javaban fetchelik a kurzort.
-
nyunyu
félisten
válasz
kw3v865
#4459
üzenetére
Mi volt a baj az eredeti elképzeléseddel?
FOR nem a mögé írt query által visszaadott sorrendben megy végig a sorokon, mint ahogyan a kurzorok tennék? De.
Indexelős ötleted nagyon elborult, egyrészt nehéz megvalósítani, pl. mi van akkor, ha jön egy új elem a táblába, akkor minden sort megupdatelsz az aktuális sorrend alapján?
Iszonyúan nagy overheadet produkálnának az ehhez szükséges triggerek.Ha csak annyi lenne a kérdés, hogyan tudod megmondani egy sorról, hogy ő valamilyen rendezés szerint hanyadik a táblában, akkor a row_number() over (order by x,y) függvényt tudod használni.
Egyébként meg a relációs adatbázisok mindig halmazokkal dolgoznak, nem egy-egy elemmel, így a más programnyelvek procedurális gondolkozásmódja (ciklusok, kurzorok...) SQLben sosem ad jó teljesítményt.
Próbálj inkább úgy gondolkozni, hogyan lehet egy queryvel az összes adatot egyszerre frissíteni/beszúrni.Előző projekten amúgy belefutottam hasonlóba, mint amit most szeretnél.
Örököltem egy kódot, ami egy táblából csinált egy rendezett kurzort, majd azon ment végig egyesével, és dinamikus SQLben kért új értéket egy szekvenciából, majd updatelte rá a tábla soraira, kvázi új indexet vezetett be.
Persze, hogy 15000 sor esetén húsz percig szöszmötölt rajta az Oracle.
Megoldás az lett, hogy egy segédtáblába leválogattam a fő tábla azonosítóit, meg a row_number() over (order by x,y) rn-t, aztán következett egy jól irányzott merge a fő táblára.
Egyből lefut 10 másodperc alatt... -
válasz
kw3v865
#4390
üzenetére
a postgresql is tud olyat, hogy ip címre vagy tartományra korlátozni a klienseket, illetve ugyanezt tűzfallal is meg lehet oldani. ez akkor jó, ha a klienseknek ismert az ip címtartománya.
elvileg használ ssl-t, tehát akár azt is meg lehet csinálni, hogy csak ismert kulcsú klienseket beengedni.
hogy ez mennyire biztonságos, az attól is függ, hogy milyen adatokat teszel bele.
a másik lehetőség, én valószínűleg ezt választanám, hogy az insert utasításokat kiírom egy text fájlba, azt rsync+ssh-val szinkronizálnám a szerverre, és ott betölteném adatbázisba.
A db-ben hosztolt adatbázisról meg annyit, hogy a benne tárolt adatok fajtájától és a hozzá tartozó szabályzatoktól, eljárásrendtől függően (úgy értem: ezek nem elegendően precíz meghatározása esetén) akár 2 év börtönnel fenyegetett bűncselekmény is lehet felhőbe adatbázist rakni.
Az api api hátán api-val megbolondítva típusú túltervezettségről továbbra is az a véleményem, hogy semmi értelme, mert egy saját fejlesztésű apiban nagyobb valószínűséggel lesz bug, mint egy postgresql net protokollban, vagyis olyan plusz energiabefektetés, ami sose térül meg, csak ront a helyzeten.
-
-
Lortech
addikt
válasz
kw3v865
#4380
üzenetére
Mert a formatos megoldásod dollar quotingot használ, ami a jobban olvasható, biztosabb, egyszóval a javasolt megoldás.
Ha visszamegyünk az eredeti statikus, működő insert statementedhez:
INSERT INTO tesztsema.table (azonosito, nev) SELECT 2332,'xyz';
Az volt a cél, hogy ezt a stringet dinamikusan előállítsd, és átadd az EXECUTE statementnek.
Azt pedig úgy tudod megtenni, hogy aposztrófokat is odateszed a példában az xyz köré.
A '||name csak annyit csinál, hogy a name értékét hozzáfűzi a stringhez, de aposztrófok ettől még nem lesznek körülötte, és text típusnál ez szükséges. Szóval, vagy te fűzöd oda (nem javasolt, csak a probléma megértéséért említettem az előző hozzászólásomban), vagy dollar quotingot vagy quote_literal() / quote_ident() fgv-t használsz.Másikhoz. Ilyen szerkezet nincs, hogy IF EXECUTE
Olyan tudsz csinálni, hogy
EXECUTE STATEMENT into VAR és a VAR értékét vizsgálod IF-fel. -
Lortech
addikt
válasz
kw3v865
#4377
üzenetére
'INSERT INTO '||$1||'.table (azonosito, nev) SELECT '||id||','||name;
>>
kiértékelés után: INSERT INTO abc.table (azonosito, nev) SELECT id_erteke, name_erteke;
Hiányzik tehát id és name változó értékei körül az aposztróf, különben azt hiszi, hogy nem egy literál, hanem egy oszlop, azért nem találja. (az id azért oké, mert number típus gondolom)
Aposztróf escape-eléséhez duplázni kell. -
Apollo17hu
őstag
válasz
kw3v865
#4122
üzenetére
Így?
SELECT tabla.mezo
,substr(tabla.mezo, instr(tabla.mezo, '"ref"=>""') + length('"ref"=>""')) relevans_adattartalom
FROM (SELECT 'asfasf saf"ref"=>""ez kell' mezo
FROM dual
UNION
SELECT 'asfasf ssadfalksijdfkeefaf "ref"=>""ez is kell, de ez hosszabb' mezo
FROM dual) tablaSubstr utolsó paraméterét elhagyva a mező utolsó karakteréig mindent leválogat. Ha nem jó, akkor mindenképp kell egy ismérv/logika, ami meghatározza a releváns karaktersorozat végét.
-
-
-
-
válasz
kw3v865
#3900
üzenetére
ha postgresql-hez kötött megoldás is megfelel, akkor:
where id = (select last_value from table_id_seq);ezzel a lekérdezéssel bármikor le tudod kérdezni a legutolsó id-t. de ez nem szép.
ha az adott sessionben raktad bele a sort, akkor egy fokkal rendesebben néz ki:
where id = (select currval('table_id_seq'));vagy, szerintem a legjobb megoldás, kérdezd le, hogy milyen értéket szúrt be az insert, ha ez megoldható:
insert blablab returning id;ezt akkor tudod használni, ha az insertet akkor csinálod, amikor az id-je is kell.
-
Ispy
nagyúr
válasz
kw3v865
#3860
üzenetére
Ötlet, én így csinálnám (nincsen tapasztalatom ekkora táblával, szkuzi):
- hozzáadsz egy ID mezőt a táblához, running number 1-8000000-ig folyamatos sorszámod lesz, sorba rendezés, ahogy neked sorba kellenek az adatok
- joinolod a táblát saját magához úgy, hogy tábla1 ID=tábla2ID+1, igy kapni fogsz egy olyan lekérdezést, ahol minden tábla1 sor mellett ott lesz a következő sor adatai
- ráereszted a függvényt az updattel
- én a helyedben tesztelném mondjuk a megoldást 100k adattal és ha jó, akkor darabokban futtatnám a taskot nem egyben, mert a világ összes memóriája sem lesz elég, pláne ha tranzakcióban fut az update.... -
válasz
kw3v865
#3860
üzenetére
ha az a kérdés, hogy hogyan hozod össze a rekordot meg az utána következő rekordot, akkor ebből inspirálódhatsz:
lehet táblának saját magával vett descartes szorzatát venni:
select t1.*,t2.* from tabla t1, tabla t2;
ezt a te esetedben nagyjából így kellene alkalmazni:
select t1.*,fuggveny(t1.masvalami,t2.masvalami) from tabla t1, tabla t2 where t1.id+1=t2.id;
ebből meg tudod faragni az udapte utasítást.
ha egy 8 millió soros táblára ráborítod, jusson eszedbe, hogy adatbáziskezelésnél a sok ramot csak a mégtöbb ram pótolhatja

-
kw3v865
senior tag
válasz
kw3v865
#3833
üzenetére
Na, elvileg megoldottam, így:

for rec in
select format('copy(select valami from table where nev=''%s'' order by gid)
to ''%s'' with csv delimiter '';'' HEADER',nev,telepules,'C:/eredmeny/'||telepules||'_'||nev||'.csv' ) scr from(
Select distinct nev, telepules from tabla)t
loop
execute rec.scr;
end loop;Azért még leellenőrzöm alaposan, hogy tényleg jó-e.
-
-
-
válasz
kw3v865
#3665
üzenetére
annak a true-nak meg false-nek nem sok értelmét látom, mert ha védett régióban van, akkor a védett régió neve oszlop nem null lesz, ha meg nem ott van, akkor igen.
viszont ez nem kellene, hogy sokat lassítson, mert a postgresql elméletileg becacheli az adatokat meg az eredményeket.
ha a kifejezés elé írsz egy explain-t, akkor megmondja az optimalizáló, hogy mit fog csinálni. azt érdemes bogarászgatni.
szerk: azt az egész case-t ki lehetne váltani szerintem úgy, hogy a lekérdezett mezők közé felveszed a védett régió nevét, és egy coalesce-vel beleírsz valamit, ha üres: coalesce(pr.name,'FALSE') as name.
-
-
DS39
nagyúr
válasz
kw3v865
#3404
üzenetére
értem, akkor javítsuk meg az update-es megoldásodat:

(itt ugye csak a subquery-vel volt gond, azt én így orvosolnám)ALTER TRIGGER nepesseg_szum ON OVEZETEK
AFTER INSERT
AS
BEGINDECLARE @TERULET GEOMETRY
DECLARE @ID INTDECLARE @kurzor CURSOR
SET @kurzor = cursor FOR
SELECT SHAPE, OBJECTID FROM INSERTEDOPEN @kurzor
FETCH NEXT FROM @kurzor INTO @TERULET, @IDWHILE @@FETCH_STATUS = 0
BEGINUPDATE OVEZETEK
SET Nepesseg_ossz = (SELECT SUM(n.lakosok) from NEPESSEG_EOV N WHERE N.SHAPE.STWithin(@TERULET)=1)
WHERE OVEZETEK.OBJECTID=@IDFETCH NEXT FROM @kurzor INTO @TERULET, @ID
ENDCLOSE @kurzor
DEALLOCATE @kurzor
END;a kiemelt részt módosítottam, kivettem a belső selectet, ott felesleges, ha a kurzorban van már az id.
-
kw3v865
senior tag
válasz
kw3v865
#3403
üzenetére
Egyébként én valószínűnek tartom, hogy a PK (OBJECTID) okozhat gondokat, mert amíg csak UPDATE-elem, nincs gond, mindig növekszik szépen eggyel.
http://desktop.arcgis.com/en/arcmap/latest/manage-data/using-sql-with-gdbs/object-id.htmKicsit összekavarodnak a dolgok, amikor nem az ArcGIS adja az értéket az ObjectID-nak, viszont enélkül sem megy, mert ez a PK (és muszáj, hogy legyen egy PK).
-
DS39
nagyúr
válasz
kw3v865
#3399
üzenetére
túlbonyolítod, de itt:
@ID=(SELECT OBJECTID FROM INSERTED)
minek a kurzor, ha itt benne hagyod azt a belső selected ami több sort fog visszahozni.
miért nem csinálod úgy ahogy írtam az elején?

ALTER TRIGGER nepesseg_szum ON OVEZETEK
INSTEAD OF INSERT
AS
BEGIN--és a triggeren belül insertálod
INSERT INTO OVEZETEK (oszlopnevek....)
SELECT oszlop1, oszlop2,
(SELECT SUM (TELEPULES.LAKOSOK) FROM TELEPULES
WHERE TELEPULES.SHAPE.STWithin(I.SHAPE)=1),
oszlop4, oszlop5 ....
FROM INSERTED IEND
--(kb ennyi, csak egészítsd ki a tényleges oszlopnevekkel a selectben, és az insert into sorban)ne after insert után update-elj, hanem eleve ne engedd addig az insertet a táblába míg át nem alakítod úgy az eredményt, ahogy neked megfelelő.
így szerintem nem kapnál eleve ilyen hibaüzenetet, hiszen az inserted táblában soronként egy SHAPE érték lesz, ezért a SUM is csak egy értéket ad vissza.
-
DS39
nagyúr
válasz
kw3v865
#3394
üzenetére
Szia!
Ezt úgy lehet megoldani, hogy megnézed mi lenne insertálva:
INSTEAD OF INSERT
AS
BEGININSERT INTO TABLANEV (oszlopnevek....)
SELECT oszlopnevek...
FROM INSERTED IEND
--------
itt a SELECT-en belül használhatsz CASE WHEN-eket, hogy adott oszlop értéke ha ez, akkor legyen helyette amaz. remélem érted
Új hozzászólás Aktív témák
- Vadonatúj, bontatlan iScooter i9Max elektromos roller, 1 év gari 35 km/h
- ADATA XPG Lancer Blade 32GB (2x16GB) DDR5 6000MHz CL34 - XMP/EXPO - 120 hó garancia
- Kingston FURY Beast 64GB (2x32GB) DDR5 6400MHz CL32 - XMP/EXPO - 120 hó garancia
- Kingston FURY Beast 32GB (1x32GB) DDR5 5200MHz CL40 - XMP/EXPO - 120 hó garancia
- Kingston FURY Beast 32GB (1x32GB) DDR5 6400MHz CL32 - XMP/EXPO - 120 hó garancia
- Keresünk iPhone 15/15 Plus/15 Pro/15 Pro Max
- GYÖNYÖRŰ iPhone 13 Mini 128GB Blue- 1 ÉV GARANCIA -Kártyafüggetlen, MS4067,94% Akksi
- GYÖNYÖRŰ iPhone 13 Mini 128GB Green- 1 ÉV GARANCIA -Kártyafüggetlen, MS4200
- Új, Aktiválatlan iPhone 17 Pro (256 GB) (rendelhető)
- HIBÁTLAN iPhone 13 Pro Max 256GB Sierra Blue-1 ÉV GARANCIA - Kártyafüggetlen, MS4224
Állásajánlatok
Cég: PCMENTOR SZERVIZ KFT.
Város: Budapest
Cég: Laptopszaki Kft.
Város: Budapest






