Тук действат редица фактори:
- Закъснение в мрежата и закъснения при двупосочно пътуване
- Резервни разходи за всеки израз в PostgreSQL
- Превключватели на контекста и забавяния на планировчика
COMMIT
разходи, ако за хора, които правят по един комит на вмъкване (вие не сте)COPY
-специфични оптимизации за насипно натоварване
Забавяне на мрежата
Ако сървърът е отдалечен, може да "плащате" на "цена" с фиксирано време за извлечение от, да речем, 50 мс (1/20-та от секундата). Или много повече за някои облачни БД. Тъй като следващото вмъкване не може да започне, докато последното не завърши успешно, това означава, че вашият максимален скоростта на вмъкване е 1000/round-trip-latency-in-ms редове в секунда. При латентност от 50 мс („време за пинг“), това е 20 реда/секунда. Дори на локален сървър това забавяне е различно от нула. Като се има предвид COPY
просто запълва прозорците за изпращане и получаване на TCP и предава поточно редове толкова бързо, колкото DB може да ги запише и мрежата може да ги прехвърли. Не се влияе много от забавянето и може да вмъква хиляди редове в секунда в една и съща мрежова връзка.
Разходи за изявление в PostgreSQL
Също така има разходи за анализиране, планиране и изпълнение на оператор в PostgreSQL. Трябва да взема ключалки, отваряне на релационни файлове, търсене на индекси и т.н. COPY
се опитва да направи всичко това веднъж, в началото, след което просто се фокусира върху зареждането на редове възможно най-бързо.
Разходи за превключване между задача/контекст
Има допълнителни времеви разходи, заплатени поради това, че операционната система трябва да превключва между postgres, който чака ред, докато приложението ви го подготвя и изпраща, и след това приложението ви чака отговор на postgres, докато postgres обработва реда. Всеки път, когато преминавате от едно към друго, губите малко време. Потенциално се губи повече време за спиране и възобновяване на различни състояния на ядрото от ниско ниво, когато процесите влизат и напускат състояния на изчакване.
Пропускане на COPY оптимизации
На всичкото отгоре COPY
има някои оптимизации, които може да използва за някои видове товари. Ако няма генериран ключ и всички стойности по подразбиране са константи например, той може да ги изчисли предварително и да заобиколи напълно изпълнителя, бързо зареждайки данни в таблицата на по-ниско ниво, което пропуска част от нормалната работа на PostgreSQL изцяло. Ако CREATE TABLE
или TRUNCATE
в същата транзакция, която COPY
, той може да направи още повече трикове за ускоряване на натоварването, като заобикаля нормалното водене на транзакции, необходимо в многоклиентска база данни.
Въпреки това COPY
на PostgreSQL все още може да направи много повече, за да ускори нещата, неща, които все още не знае как да направи. Може автоматично да пропусне актуализациите на индекси, след което да възстанови индексите, ако променяте повече от определена част от таблицата. Може да прави актуализации на индекси на партиди. Много повече.
Поемане на разходи
Едно последно нещо, което трябва да вземете предвид, са разходите за ангажимент. Вероятно не е проблем за вас, защото psycopg2
по подразбиране отваря транзакция и не се ангажира, докато не го кажете. Освен ако не сте му казали да използва autocommit. Но за много DB драйвери автоматичното записване е по подразбиране. В такива случаи ще правите един комит за всеки INSERT
. Това означава едно изтриване на диск, при което сървърът се уверява, че записва всички данни в паметта на диска и казва на дисковете да запишат собствените си кешове в постоянно съхранение. Това може да отнеме дълго време и варира много в зависимост от хардуера. Моят NVMe BTRFS лаптоп, базиран на SSD, може да направи само 200 fsync/секунда, срещу 300 000 несинхронизирани записа/секунда. Така че ще зареди само 200 реда/секунда! Някои сървъри могат да правят само 50 fsync/секунда. Някои могат да направят 20 000. Така че, ако трябва редовно да извършвате ангажименти, опитайте се да зареждате и извършвате на партиди, правете многоредови вмъквания и т.н. Тъй като COPY
само един ангажимент в края, разходите за ангажимент са незначителни. Но това също означава COPY
не може да се възстанови от грешки по средата на данните; отменя цялото насипно натоварване.