Výkonnostní spiky v trvání queries v Postgres

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #15 kdy: 29. 05. 2024, 15:30:54 »
Já jsem ten předchozí příspěvek smazal, protože ačkoliv vypnutí oněch "bočních" jobů vyredukovalo spiky v DB, nevyredukovalo to všechny spiky.

Přesto myslím si stále to, že by to mělo mít lepší performance, když se dělají "boční" queries do databáze.

"Bloatnutá" tabulka předpokládám je řešené přes Vacuum analyse. Tento spouštím každou noc nad všemi tabulkami.

Tabulka má 10mil. řádků a 40 sloupců. Shared buffer je momentálně na 4GB při 16GB RAM. Velikost tabulky je 8.5GB.

Jak je tedy vidět, tabulka má 2x větší velikost než shared buffer. Nejsem si však jist jaký toto má vliv. Pokud to však není dobře, očekávám že partitioning tabulky do 10 podtabulek by tento problém snad mohl vyřešit, pokud se nemýlím.


Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #16 kdy: 29. 05. 2024, 17:18:54 »
Já jsem ten předchozí příspěvek smazal, protože ačkoliv vypnutí oněch "bočních" jobů vyredukovalo spiky v DB, nevyredukovalo to všechny spiky.

Přesto myslím si stále to, že by to mělo mít lepší performance, když se dělají "boční" queries do databáze.

"Bloatnutá" tabulka předpokládám je řešené přes Vacuum analyse. Tento spouštím každou noc nad všemi tabulkami.

Tabulka má 10mil. řádků a 40 sloupců. Shared buffer je momentálně na 4GB při 16GB RAM. Velikost tabulky je 8.5GB.

Jak je tedy vidět, tabulka má 2x větší velikost než shared buffer. Nejsem si však jist jaký toto má vliv. Pokud to však není dobře, očekávám že partitioning tabulky do 10 podtabulek by tento problém snad mohl vyřešit, pokud se nemýlím.

VACUUM ANALYZE bloating neresi - ten resi VACUUM FULL. Jestli mate tabulku 8.5GB, a ctete ji kazdych 30 sec, tak jenom tim si utavite IO. I docela slusne IO vam dava 1GB/s - a jste vyrazne nad shared buffers, takze si proplachujete shard buffers - sice asi jenom jednu tretinu, coz je 1GB, ale to se muze nacitat z disku, a v momentu, kdy intenzivne ctete, tak muzete mit problem. Tam je otazka, jake tam mate indexy a co se vsechno musi pouzit temi ostatnimi dotazy. Pokud tam mate lagy nad 100ms, tak uz by se mozna dalo videt neco i v pg_stat_activity, jsou tam videt zamky. Partitioning vam nijak nepomuze, pokud budete cist vsechny partisny. Pokud chcete, aby se vam to chovalo +/- jako realtime system, tak chca nechca musite mit dost velkou rezervu v hw. Partitioning by vam mohl pomoct s mazanim, nebo snizenim rezie autovacuua, pokud do starsich partitions nezapisujete.

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #17 kdy: 29. 05. 2024, 17:53:39 »
Nj, jenže je otázka, co to je to čtení každých 30s.

Pakliže já mám dobře udělané indexy, tak queries mi vrací max řekněme 100 záznamů. Co na tom záleží, že je tam 8GB dat, když podle index scanu se jich načte z tabulky jen třeba 100.

Problém můžou být queries typu ORDER BY date OFFSET  250000 LIMIT 500, ty dokážou spolehlivě vytvořit spike, trvají přibližně 2 vteřiny.

Zajímavé je, že už třeba query ORDER BY date OFFSET 500000 LIMIT 1000 dokáže v 50% případů trvat přes 30s, tipuju že se to občas přepne na sequential scan.

Nicméně tyto queries tam samozřejmě nespouštím běžně, říkám jen, že dokáží způsobit spike a request co trvá 30ms rázem trvá přes 300ms.

Neodpustím si však poznámku, že nakolik ORDER BY date OFFSET 500000 LIMIT 1000 zní šíleně, pořád by to mělo být přes index, tzn. těch 1000 řádků si to nejprve najde přes index, a potom z tabulky si to natáhne oněch 1000 záznamů přes random access. Nelíbí se mi, že to způsobí spike, protože to přece není zase taková hrůza, jak se zdá. To Postgres tam něco "vyvádí".

Zároveň s tím, ORDER BY date OFFSET  250000 LIMIT 500 si nemyslím že by mělo trvat 2 sekundy, když to jde přes index. Přijde mi to jako moc.

Líbilo by se mi, kdyby to dokázalo udělat OFFSET 500000 LIMIT 1000 a zároveň s tím by mi délka hlavních requestu nepřekročila 300ms. Kdyby to zvládlo tohle, měl bych klid a jistotu, že DB je dostatečně dimenzovaná.
« Poslední změna: 29. 05. 2024, 17:57:22 od registrovany123 »

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #18 kdy: 29. 05. 2024, 18:25:29 »
Nicméně tyto queries tam samozřejmě nespouštím běžně, říkám jen, že dokáží způsobit spike a r
Neodpustím si však poznámku, že nakolik ORDER BY date OFFSET 500000 LIMIT 1000 zní šíleně, pořád by to mělo být přes index, tzn. těch 1000 řádků si to nejprve najde přes index, a potom z tabulky si to natáhne oněch 1000 záznamů přes random access. Nelíbí se mi, že to způsobí spike, protože to přece není zase taková hrůza, jak se zdá. To Postgres tam něco "vyvádí".

OFFSET neznamená jump na pozici - znamená zahoď, co jsi spočítal - takže když tam máte OFFSET 500000 LIMIT 1000, tak se samozřejmě index nepoužije - jelikož čtete víc než čtvrtinu tabulky.  Tohle nemůže fungovat - jestli stránkuje tímhle mechanismem, tak je hodně nešťastné - buďto to musíte převést na WHERE id > x LIMIT 1000 nebo používat kurzor a postupně si fetchovat.

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #19 kdy: 29. 05. 2024, 18:36:48 »
Nicméně tyto queries tam samozřejmě nespouštím běžně, říkám jen, že dokáží způsobit spike a r
Neodpustím si však poznámku, že nakolik ORDER BY date OFFSET 500000 LIMIT 1000 zní šíleně, pořád by to mělo být přes index, tzn. těch 1000 řádků si to nejprve najde přes index, a potom z tabulky si to natáhne oněch 1000 záznamů přes random access. Nelíbí se mi, že to způsobí spike, protože to přece není zase taková hrůza, jak se zdá. To Postgres tam něco "vyvádí".

OFFSET neznamená jump na pozici - znamená zahoď, co jsi spočítal - takže když tam máte OFFSET 500000 LIMIT 1000, tak se samozřejmě index nepoužije - jelikož čtete víc než čtvrtinu tabulky.  Tohle nemůže fungovat - jestli stránkuje tímhle mechanismem, tak je hodně nešťastné - buďto to musíte převést na WHERE id > x LIMIT 1000 nebo používat kurzor a postupně si fetchovat.

Dobře řekněme že mám tabulku:

Objednavky

A mám tam 10 mil záznamů. A udělám:

SELECT *
FROM Objednavky
ORDER BY date ASC
OFFSET 250000
LIMIT 500

A mám index:

CREATE INDEX idx0 ON Objednavky (date ASC)


Tak potom query plan by měl postupovat takto:

1. Vlezu do indexu idx0
2. Ten je sortován by default ASC.
3. Přeskočím prvních 250000 záznamů z indexu
4. Vezmu následujících 500 záznamů v indexu
5. S těmi záznamy z indexu vlezu do tabulky Objednavky a načtu z disku oněch 500 záznamů přes random access.

Takto by to přece mělo fungovat, ne? Tzn. tabulka Objednávky co má 40 sloupců může mít klidně 10GB, ale index idx0 má třeba jen 500MB, a ani ty se nemusí přečíst všechny, stačí nad tím indexem, tzn. souborem na disku, udělat iteraci 250000 záznamů a dalších 500 vrať.

Někdy bych byl rači kdybych si ty query plany mohl psát sám.
« Poslední změna: 29. 05. 2024, 18:39:52 od registrovany123 »


Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #20 kdy: 29. 05. 2024, 19:18:48 »

Takto by to přece mělo fungovat, ne? Tzn. tabulka Objednávky co má 40 sloupců může mít klidně 10GB, ale index idx0 má třeba jen 500MB, a ani ty se nemusí přečíst všechny, stačí nad tím indexem, tzn. souborem na disku, udělat iteraci 250000 záznamů a dalších 500 vrať.

Někdy bych byl rači kdybych si ty query plany mohl psát sám.

Ne tak to nefunguje - tabulka není pole - je to halda, kde data mohou být kdekoliv - řádky nejsou očíslované. Možná si index můžete vynutit použitím ORDER BY - nicméně pořád se bude skrz index číst 250000 záznamů, což je zoufale pomalé. I kdybyste si ty query plány psal sám, tak by vám to bylo k ničemu, jelikož v relační databázi není žádná rychlá možnost skoku na ntý záznam. V historických databázích s fixní délkou věty to šlo, pokud jste z tabulky nikdy nemazali, ale v moderních relačních databázích s proměnlivou délkou věty žádná taková magie není.

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #21 kdy: 29. 05. 2024, 20:02:49 »

Takto by to přece mělo fungovat, ne? Tzn. tabulka Objednávky co má 40 sloupců může mít klidně 10GB, ale index idx0 má třeba jen 500MB, a ani ty se nemusí přečíst všechny, stačí nad tím indexem, tzn. souborem na disku, udělat iteraci 250000 záznamů a dalších 500 vrať.

Někdy bych byl rači kdybych si ty query plany mohl psát sám.

Ne tak to nefunguje - tabulka není pole - je to halda, kde data mohou být kdekoliv - řádky nejsou očíslované. Možná si index můžete vynutit použitím ORDER BY - nicméně pořád se bude skrz index číst 250000 záznamů, což je zoufale pomalé. I kdybyste si ty query plány psal sám, tak by vám to bylo k ničemu, jelikož v relační databázi není žádná rychlá možnost skoku na ntý záznam. V historických databázích s fixní délkou věty to šlo, pokud jste z tabulky nikdy nemazali, ale v moderních relačních databázích s proměnlivou délkou věty žádná taková magie není.

No počkat, tohle bych potřeboval líp pochopit. Databáze si přece i na disku dělá svoje speciální soubory, a měl jsem i v představě či v naději, že si to umí pracovat až s jednotlivými bloky na disku.

Pokud vy si v indexu najdete přes query 1 zázname přes equals, tak ten index musí vrátit nějaký identifikátor, ne? A ten identifikátor to musí být něco, jak vytáhne ten záznam z té originální velké tabulky.

Tzn. index "něco" vrátí, a databáze na to něco v tabulce dokáže "skočit", a když ne skočit tam přímo, tak alespoň přibližně skočit někam, proiterovat omezenou množinu dat, najít záznam a vrátit ho. Jako Hashmapa.

Technicky vzato, když se nad tím zamyslím jako programátor. Mám nějakou tabulku, tak ji budu reprezentovat soubory na disku. Těch souborů tam může být třeba 100000. A když mi někdo řekne "Dej mi záznam "93fj2fj209fjh2dgrd3109f92", tak já vím, že tento záznam bude v souboru s číslem 12344.

Takhle v principu tpo přece nějak musí umět fungovat, ne? Nehledě na to, že technicky vzato můžu na SSD disk se speciálním naformátováním vkládat záznamy do jednotlivých bloků, každému bloku dám identifkátor, a potom s tím SSD diskem rovnou skočím na daný blok. I tohle technicky vzato je proveditelné, že můžu na záznam skočit přímo. A když ne přímo, tak alespoň na nějaký agregační uzel, a z něj už potom přímo.

Tak by mě zajímalo jak to dělá postgres.
« Poslední změna: 29. 05. 2024, 20:06:21 od registrovany123 »

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #22 kdy: 29. 05. 2024, 20:35:37 »

Takhle v principu tpo přece nějak musí umět fungovat, ne? Nehledě na to, že technicky vzato můžu na SSD disk se speciálním naformátováním vkládat záznamy do jednotlivých bloků, každému bloku dám identifkátor, a potom s tím SSD diskem rovnou skočím na daný blok. I tohle technicky vzato je proveditelné, že můžu na záznam skočit přímo. A když ne přímo, tak alespoň na nějaký agregační uzel, a z něj už potom přímo.

Tak by mě zajímalo jak to dělá postgres.

Databáze označuje řádky číslem datové stránky a pozicí na stránce - můžete se jednoduše a rychle přesunout na 100 stránku a 10 řádek na této stránce. Ale nikdy nevíte kolikátý je to řádek od začátku tabulky (nevíte kolik je řádku před a nevíte kolik je řádků za). Taková informace nikde není - a kdyby byla, nedal by se udělat jednoduše DELETE, nebo třeba v Postgresu UPDATE atd. Relační databáze jsou založené na tom, že relace (tabulka) je množina - v množině nemáte očíslované hodnoty. Má to svoje výhody, má to svoje nevýhody. Nevýhodou je třeba pomalý OFFSET - který redukuje jen obsah přenášený po síti. Skrz index můžete mít pekelně rychlou operaci WHERE id > než ale nikdy skoč na 30 řádek, jelikož taková informace tam prostě není.

Můžete si udělat nějaký vlastní hash partitioning nebo list partitioning. Nicméně s větší přesností vám poroste počet souborů počet partitions a pekelně se zpomalí optimalizace, a brutálně vám vzrostou nároky na paměť při optimalizaci dotazu. A uvnitř partitions zase nebudete vědět kolik je tam řádků a kde ten správný řádek je. Vy si můžete napsat jednoduchou aplikaci, která bude pracovat se souborem direktivně s pevnou délkou věty a bude vám to fungovat - a v podstatě budete simulovat databáze 1 generace, které uměly velice rychle seekovat. Ale třeba už se nedala udělat jednoduše defragmentace. Relační databáze jsou db 2 generace, které schválně datový model nezávisí na fyzické pozici - mne jako uživatele nezajímá, kde je konkrétně řádek (a v postgresu se při každém update jeho pozice mění), ale seek na ntý řádek v relační db jednoduše neuděláte. Ve speciálních případech, kdy id bude totožné s pozicí, tak vám index pomůže - ale opět nemůžete použít OFFSET, jelikož pro relační db, je něco podobného nepředstavitelné - a) nesměl byste mazat z db, a každý INSERT by se musel povést.

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #23 kdy: 30. 05. 2024, 08:27:45 »

Takhle v principu tpo přece nějak musí umět fungovat, ne? Nehledě na to, že technicky vzato můžu na SSD disk se speciálním naformátováním vkládat záznamy do jednotlivých bloků, každému bloku dám identifkátor, a potom s tím SSD diskem rovnou skočím na daný blok. I tohle technicky vzato je proveditelné, že můžu na záznam skočit přímo. A když ne přímo, tak alespoň na nějaký agregační uzel, a z něj už potom přímo.

Tak by mě zajímalo jak to dělá postgres.

Databáze označuje řádky číslem datové stránky a pozicí na stránce - můžete se jednoduše a rychle přesunout na 100 stránku a 10 řádek na této stránce. Ale nikdy nevíte kolikátý je to řádek od začátku tabulky (nevíte kolik je řádku před a nevíte kolik je řádků za).

Ale to přece víte, protože jste na tu 100 stránku a 10 řádek skočil prostřednictvím toho indexu. A vy podle indexu víte, že to je offset 10000 třeba.

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #24 kdy: 30. 05. 2024, 11:10:12 »

Takhle v principu tpo přece nějak musí umět fungovat, ne? Nehledě na to, že technicky vzato můžu na SSD disk se speciálním naformátováním vkládat záznamy do jednotlivých bloků, každému bloku dám identifkátor, a potom s tím SSD diskem rovnou skočím na daný blok. I tohle technicky vzato je proveditelné, že můžu na záznam skočit přímo. A když ne přímo, tak alespoň na nějaký agregační uzel, a z něj už potom přímo.

Tak by mě zajímalo jak to dělá postgres.

Databáze označuje řádky číslem datové stránky a pozicí na stránce - můžete se jednoduše a rychle přesunout na 100 stránku a 10 řádek na této stránce. Ale nikdy nevíte kolikátý je to řádek od začátku tabulky (nevíte kolik je řádku před a nevíte kolik je řádků za).

Ale to přece víte, protože jste na tu 100 stránku a 10 řádek skočil prostřednictvím toho indexu. A vy podle indexu víte, že to je offset 10000 třeba.

Ale ani v indexu není nikde informace, že nějaký řádek má offset 10000. Musíte se proiterovat indexem, což u velkých tabulek, které se vám nevejdou do RAM je výrazně horší než sekvenční IO, jelikož tam máte random IO operace. Pokud nemáte extra širokou tabulku, tak je většinou výrazně rychlejší přečíst tabulku sekvenčně než skrz index náhdoně. Dnes s SSD to už není řádový rozdíl, ale pořád tam nějaký rozdíl je.

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #25 kdy: 30. 05. 2024, 11:45:03 »
Jasně tomu rozumím a dává mi smysl, že když řeknu postgres:

ORDER BY date OFFSET 250000 LIMIT 500

Tak použije index a query je hotový ve stovkách ms. A když řeknu Postgres

ORDE BY date OFFSET 500000 LIMIT 1000

Tak už query trvá přes 10 vteřin, protože se postgres přepne.

Ale: Kdyby se to nepřeplo, tak to určitě nebude trvat několik vteřin ale prostě násobek toho horního času. Tzn. já vím, že by theory někde je řečeno, že v určitých situacích je seq scan rychlejší než index scan s následným randomom access, ale v >> praxi <<, protože ladím postgres queries posledních 5 let často, tak jasně vidím, že seq scan zpravidla nikdy nechci, protože trvá >> násobně << déle. V praxi.

Takže někde "in RDB theory" je lepší seq. scan, ale v praxi já jasně vidím, že zpravidla vždycky je lepší index scan.

Taky kolikrát jsem zuřil když jsem hledal, proč mi pg přepne na seq. scan, a X-krát jsem četl, že je seq scan výhodnější v určitých situacích, a já přitom jasně vidím, že je násobně nevýhodnější, a vidím to jasně i teď u výše uvedených queries.

A potom co se týká toho ORDER BY, tak já asi pořád nesouhlasím s vám v tom, že to neumí zjistit OFFSET 10000 hned indexu. Protože ty indexy jsou sortovány. Pakliže já mám v indexu sortovány záznamy podle datumu Ascending, tak můžu skočit na záznam č. 10001 v INDEXU, a vím, že je na stránce 12345 na řádku 123. Z indexu si pak načtu pozice dalších 500 záznamů a vím, že jsou sorted a že jsou OFFSET 10000 v tabulce.

By theory jistojistě to udělat takto lze, technicky. O tom jsem přesvědčen. jestli to však je v silách Postgres to nevím. Já na vlasnní oči viděl, jaké dokáže Postgres query engine dělat do očí bijící nesmysly.

Jako např. že si je schopno počítat json_agg funkce a jine funkce v SELECTU u záznamů, které nejsou vráceny v konečném
výsledku dotazu, a zpomalí tím query násobně.

Nebo to, že Postgres nedokáže optimalizovat Views používané ve FROM klauzuli v jiném View, tzn. nedokáže jakoby "mergnout" a optimalizovat 2 selecty ve 2 Views. A tak namísto Views já musím uděla strašný copy-paste a použít jeden obří SQL query, aby Postgrs pochopilo, že některé věci může vykrátit. Katastrofa, a vede to k velkému nepořádku, protože Views mají velké SQL queries schovávat.
« Poslední změna: 30. 05. 2024, 11:50:35 od registrovany123 »

Logik

  • *****
  • 1 035
    • Zobrazit profil
    • E-mail
Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #26 kdy: 30. 05. 2024, 11:54:06 »
Citace
Ale ani v indexu není nikde informace,
Myslím, že tazatel naráží na "Index only access", které některé MVCC databáze co vím mají. Je to ale něco za něco, jestlitomu rozumím dobře, tak to znamená přepisovat do indexů informace o tom, zdali je záznam commited nebo ne, což znamená další IO režii navíc při zápisech (a kdovíjaké další problémy). Postgresql to do indexů co vím nezapisuje, takže nemůže tuto techniku použít.

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #27 kdy: 30. 05. 2024, 12:03:39 »
Jasně tomu rozumím a dává mi smysl, že když řeknu postgres:

ORDER BY date OFFSET 250000 LIMIT 500

Tak použije index a query je hotový ve stovkách ms. A když řeknu Postgres

ORDE BY date OFFSET 500000 LIMIT 1000

Tak už query trvá přes 10 vteřin, protože se postgres přepne.

Ale: Kdyby se to nepřeplo, tak to určitě nebude trvat několik vteřin ale prostě násobek toho horního času. Tzn. já vím, že by theory někde je řečeno, že v určitých situacích je seq scan rychlejší než index scan s následným randomom access, ale v >> praxi <<, protože ladím postgres queries posledních 5 let často, tak jasně vidím, že seq scan zpravidla nikdy nechci, protože trvá >> násobně << déle. V praxi.

Takže někde "in RDB theory" je lepší seq. scan, ale v praxi já jasně vidím, že zpravidla vždycky je lepší index scan.

Taky kolikrát jsem zuřil když jsem hledal, proč mi pg přepne na seq. scan, a X-krát jsem četl, že je seq scan výhodnější v určitých situacích, a já přitom jasně vidím, že je násobně nevýhodnější, a vidím to jasně i teď u výše uvedených queries.

A potom co se týká toho ORDER BY, tak já asi pořád nesouhlasím s vám v tom, že to neumí zjistit OFFSET 10000 hned indexu. Protože ty indexy jsou sortovány. Pakliže já mám v indexu sortovány záznamy podle datumu Ascending, tak můžu skočit na záznam č. 10001 v INDEXU, a vím, že je na stránce 12345 na řádku 123. Z indexu si pak načtu pozice dalších 500 záznamů a vím, že jsou sorted a že jsou OFFSET 10000 v tabulce.

By theory jistojistě to udělat takto lze, technicky. O tom jsem přesvědčen. jestli to však je v silách Postgres to nevím. Já na vlasnní oči viděl, jaké dokáže Postgres query engine dělat do očí bijící nesmysly.

Jako např. že si je schopno počítat json_agg funkce a jine funkce v SELECTU u záznamů, které nejsou vráceny v konečném
výsledku dotazu, a zpomalí tím query násobně.

Nebo to, že Postgres nedokáže optimalizovat Views používané ve FROM klauzuli v jiném View, tzn. nedokáže jakoby "mergnout" a optimalizovat 2 selecty ve 2 Views. A tak namísto Views já musím uděla strašný copy-paste a použít jeden obří SQL query, aby Postgrs pochopilo, že některé věci může vykrátit. Katastrofa, a vede to k velkému nepořádku, protože Views mají velké SQL queries schovávat.

Index scan budete mít rychlejší, když se vám datové stránky udrží v cache. Jinak záleží na aktuální utilizaci disku. S optimalizací indexu - je možné, že se vám u složitějších dotazů aktivuje GEQO optimalizátor, který je výrazně rychlejší, ale nemusí vrátit skutečně nejlepší plán, případně jste možná hitnul from_collapse_limit. Vaše theory je nesmysl - pokud bych umazal první řádek, musel bych regenerovat celý index, aby se přepočítaly pořadová čísla řádků. Což se samozřejmě neděje. Ne u klasických relačních databází. Existují append only databáze, ale to bychom se bavili o hodně specifických databázích.

Pozn. Postgres má jednoduché pravidlo - pokud čtete více než 1/4 tabulky, použije se seq scan. To je dáno poměrem seq_page_cost/random_page_cost. Pokud děláte s ssd nebo pokud se vám db vejde do RAM, tak můžete stáhnout random_page_cost na hodnotu 2 - někdy se stahuje i na 1.1 nebo 1.5, ale to už může dělat brikule.

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #28 kdy: 30. 05. 2024, 12:15:47 »
Citace
Ale ani v indexu není nikde informace,
Myslím, že tazatel naráží na "Index only access", které některé MVCC databáze co vím mají. Je to ale něco za něco, jestlitomu rozumím dobře, tak to znamená přepisovat do indexů informace o tom, zdali je záznam commited nebo ne, což znamená další IO režii navíc při zápisech (a kdovíjaké další problémy). Postgresql to do indexů co vím nezapisuje, takže nemůže tuto techniku použít.

Postgres má index only scan (s podporou visibility map). To vám zrychlí čtení dat, ale pořád při OFFSET 10000 musíte přečíst 10000 hodnot z indexu. Pokud chcete dělat efektivně s relačními db (nemluvím jen o Postgresu), tak OFFSET s nějakým vyšším číslem je antipattern

Re:Výkonnostní spiky v trvání queries v Postgres
« Odpověď #29 kdy: 30. 05. 2024, 12:53:32 »
Citace
Ale ani v indexu není nikde informace,
Myslím, že tazatel naráží na "Index only access", které některé MVCC databáze co vím mají. Je to ale něco za něco, jestlitomu rozumím dobře, tak to znamená přepisovat do indexů informace o tom, zdali je záznam commited nebo ne, což znamená další IO režii navíc při zápisech (a kdovíjaké další problémy). Postgresql to do indexů co vím nezapisuje, takže nemůže tuto techniku použít.

Postgres má index only scan (s podporou visibility map). To vám zrychlí čtení dat, ale pořád při OFFSET 10000 musíte přečíst 10000 hodnot z indexu. Pokud chcete dělat efektivně s relačními db (nemluvím jen o Postgresu), tak OFFSET s nějakým vyšším číslem je antipattern


K tomu antipatternu. Řekněme, že mám tabulku:

Orders(id, date)

A budu tím chtít procházet. Můžu udělat:

SELECT *
FROM Orders
ORDER BY date ASC
LIMIT 500
OFFSET 100000

Nebo můžu ud2lat:

SELECT *
FROM Orders
WHERE date > '...' AND date <= '...'

A teď mi zkuste vysvětlit, v čem bude query dole rychlejší, když to nahoře je antipatern. Jak říkám, cíl je stránkovat přes ty záznamy a vracet je přes API - to je cíl - není cíl se kochat jak se DB nenadře - máte business requirement na vaši službu a potřebujete implementovat stránkování. Buďto přes OFFSET a když je to teda antipattern, dobrá, tak tedy přes date.

Technicky vzato, v čem se ve druhé případě postgres méně nadře?

Protože v prvním případě se musi engine podívat do date_index a proiterovat prvních 100000 entries, aby si to následně vybralo 500 následujíchc entries a vytáhnout si je z tabulky Orders, kde je 10 mil záznamů.

Ve druhém případě však musí udělat totéž: musí si proiterovat date_index, zjistit, které záznamy zplňují podmínku, a potom si je vytáhnout z tabulky Orders.

To vyžaduje trochu vysvětlení, proč je v tom případě OFFSET antipatern.
« Poslední změna: 30. 05. 2024, 12:56:38 od registrovany123 »