sql >> Databáze >  >> RDS >> PostgreSQL

Jak funguje COPY a proč je mnohem rychlejší než INSERT?

Zde působí řada faktorů:

  • Latence sítě a zpáteční zpoždění
  • Režie na příkaz v PostgreSQL
  • Přepínání kontextu a zpoždění plánovače
  • COMMIT náklady, pokud pro lidi, kteří provádějí jedno potvrzení na vložku (nejste)
  • COPY -specifické optimalizace pro hromadné nakládání

Latence sítě

Pokud je server vzdálený, můžete „platit“ za příkaz pevnou časovou „cenu“, řekněme 50 ms (1/20 sekundy). Nebo mnohem více pro některé databáze hostované v cloudu. Protože další vložení nemůže začít, dokud se úspěšně nedokončí poslední, znamená to vaše maximum rychlost vkládání je 1000/zpáteční latence v ms řádcích za sekundu. Při latenci 50 ms ("ping time") je to 20 řádků/sekundu. I na místním serveru je toto zpoždění nenulové. Kde je COPY jen vyplní TCP okna pro odesílání a přijímání a streamuje řádky tak rychle, jak je může DB zapsat a síť je může přenést. Není příliš ovlivněno latencí a může vkládat tisíce řádků za sekundu na stejné síťové spojení.

Cena za výpis v PostgreSQL

Existují také náklady na analýzu, plánování a provádění příkazu v PostgreSQL. Musí mít zámky, otevírat relační soubory, vyhledávat indexy atd. COPY se to všechno pokusí udělat jednou, na začátku, pak se zaměřte na co nejrychlejší načítání řádků.

Náklady na přepínání úkolů/kontextu

Existují další časové náklady, které se platí kvůli tomu, že operační systém musí přepínat mezi postgres čekáním na řádek, zatímco vaše aplikace jej připravuje a odesílá, a poté, co vaše aplikace čeká na odpověď postgresu, zatímco postgres zpracuje řádek. Pokaždé, když přecházíte z jednoho do druhého, ztrácíte trochu času. Více času je potenciálně promarněno pozastavením a obnovením různých nízkoúrovňových stavů jádra, když procesy vstupují do čekacích stavů a ​​opouštějí je.

Chybí vám optimalizace COPY

K tomu všemu COPY má určité optimalizace, které lze použít pro některé druhy zatížení. Pokud neexistuje žádný vygenerovaný klíč a jakékoli výchozí hodnoty jsou například konstanty, může je předem vypočítat a zcela obejít exekutor, rychle načítat data do tabulky na nižší úrovni, což zcela vynechá část normální práce PostgreSQL. Pokud CREATE TABLE nebo TRUNCATE ve stejné transakci COPY , dokáže ještě více triků pro zrychlení načítání tím, že obejde běžné účetnictví transakcí potřebné v databázi pro více klientů.

Navzdory tomu COPY PostgreSQL může ještě udělat mnohem víc pro urychlení věcí, věcí, které ještě neumí. Pokud měníte více než určitou část tabulky, může automaticky přeskočit aktualizace indexů a poté znovu vytvořit indexy. Mohlo by to provádět aktualizace indexu v dávkách. Mnohem více.

Viz náklady

Poslední věcí, kterou je třeba zvážit, jsou náklady na závazek. Pravděpodobně to pro vás není problém, protože psycopg2 výchozím nastavením je otevření transakce a nepotvrzení, dokud mu to neřeknete. Pokud jste mu neřekli, aby použil autocommit. Ale pro mnoho ovladačů DB je výchozí nastavení autocommit. V takových případech byste provedli jedno potvrzení pro každý INSERT . To znamená jedno vyprázdnění disku, kdy se server ujistí, že vypíše všechna data v paměti na disk a řekne diskům, aby zapsaly své vlastní mezipaměti do trvalého úložiště. To může trvat dlouho čas a hodně se liší v závislosti na hardwaru. Můj notebook NVMe BTRFS založený na SSD dokáže provádět pouze 200 fsynců za sekundu oproti 300 000 nesynchronizovaných zápisů za sekundu. Načte se tedy pouze 200 řádků za sekundu! Některé servery mohou provádět pouze 50 fsynců za sekundu. Někteří dokážou i 20 000. Takže pokud musíte pravidelně odevzdávat, snažte se načítat a odevzdávat v dávkách, provádět víceřádkové vkládání atd. Protože COPY pouze jeden závazek na konci, náklady na potvrzení jsou zanedbatelné. To ale také znamená COPY nelze se zotavit z chyb v průběhu dat; zruší celé hromadné zatížení.



  1. Mohu požádat Postgresql, aby ignoroval chyby v transakci

  2. MySQL – kolik řádků mohu vložit do jednoho příkazu INSERT?

  3. Datový model knihovny

  4. Vytvořte parametrizované VIEW v SQL Server 2008