Postgres: bloat, pg_repack ΠΈ deferred constraints

Postgres: bloat, pg_repack ΠΈ deferred constraints

Π­Ρ„Ρ„Π΅ΠΊΡ‚ раздувания Ρ‚Π°Π±Π»ΠΈΡ† ΠΈ индСксов (bloat) ΡˆΠΈΡ€ΠΎΠΊΠΎ извСстСн ΠΈ присутствуСт Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Postgres. Π•ΡΡ‚ΡŒ способы Π±ΠΎΡ€ΡŒΠ±Ρ‹ с Π½ΠΈΠΌ β€œΠΈΠ· коробки” Π²Ρ€ΠΎΠ΄Π΅ VACUUM FULL ΠΈΠ»ΠΈ CLUSTER, Π½ΠΎ ΠΎΠ½ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‚ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π²ΠΎ врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΈ поэтому Π½Π΅ всСгда ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Ρ‹.

Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Ρ‚Π΅ΠΎΡ€ΠΈΠΈ ΠΎ Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ bloat, ΠΊΠ°ΠΊ с Π½ΠΈΠΌ ΠΌΠΎΠΆΠ½ΠΎ Π±ΠΎΡ€ΠΎΡ‚ΡŒΡΡ, ΠΎ deferred constraints ΠΈ ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ½ΠΈ привносят Π² использованиС Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ pg_repack.

Π­Ρ‚Π° ΡΡ‚Π°Ρ‚ΡŒΡ написана Π½Π° основС ΠΌΠΎΠ΅Π³ΠΎ выступлСния Π½Π° PgConf.Russia 2020.

ΠŸΠΎΡ‡Π΅ΠΌΡƒ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ bloat

Π’ основС Postgres Π»Π΅ΠΆΠΈΡ‚ многовСрсионная модСль (MVCC). Π•Ρ‘ ΡΡƒΡ‚ΡŒ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ каТдая строка Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ нСсколько вСрсий, ΠΏΡ€ΠΈ этом Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ видят Π½Π΅ Π±ΠΎΠ»Π΅Π΅ ΠΎΠ΄Π½ΠΎΠΉ ΠΈΠ· этих вСрсий, Π½ΠΎ Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΎΠ΄Π½Ρƒ ΠΈ Ρ‚Ρƒ ΠΆΠ΅. Π­Ρ‚ΠΎ позволяСт Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ нСскольким транзакциям ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΈ практичСски Π½Π΅ ΠΎΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ влияния Π΄Ρ€ΡƒΠ³ Π½Π° Π΄Ρ€ΡƒΠ³Π°.

ΠžΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ всС эти вСрсии Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ. Postgres Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ с ΠΏΠ°ΠΌΡΡ‚ΡŒΡŽ постранично ΠΈ страница – это ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±ΡŠΡ‘ΠΌ Π΄Π°Π½Π½Ρ‹Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ с диска Π»ΠΈΠ±ΠΎ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ. Π”Π°Π²Π°ΠΉΡ‚Π΅ рассмотрим нСбольшой ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ½ΡΡ‚ΡŒ ΠΊΠ°ΠΊ это происходит.

Допустим, Ρƒ нас Π΅ΡΡ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ Π΄ΠΎΠ±Π°Π²ΠΈΠ»ΠΈ нСсколько записСй. Π’ ΠΏΠ΅Ρ€Π²ΠΎΠΉ страницС Ρ„Π°ΠΉΠ»Π°, Π³Π΄Π΅ хранится Ρ‚Π°Π±Π»ΠΈΡ†Π°, появились Π½ΠΎΠ²Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅. Π­Ρ‚ΠΎ ΠΆΠΈΠ²Ρ‹Π΅ вСрсии строк, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ доступны Π΄Ρ€ΡƒΠ³ΠΈΠΌ транзакциям послС ΠΊΠΎΠΌΠΌΠΈΡ‚Π° (для простоты Π±ΡƒΠ΄Π΅ΠΌ ΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ изоляции Read Committed).

Postgres: bloat, pg_repack ΠΈ deferred constraints

Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ ΠΎΠ±Π½ΠΎΠ²ΠΈΠ»ΠΈ ΠΎΠ΄Π½Ρƒ ΠΈΠ· записСй ΠΈ Ρ‚Π΅ΠΌ самым ΠΏΠΎΠΌΠ΅Ρ‚ΠΈΠ»ΠΈ ΡΡ‚Π°Ρ€ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΠΊΠ°ΠΊ Π½Π΅Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ.

Postgres: bloat, pg_repack ΠΈ deferred constraints

Π¨Π°Π³ Π·Π° шагом, обновляя ΠΈ удаляя вСрсии строк, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ страницу, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π° Π΄Π°Π½Π½Ρ‹Ρ… – это β€œΠΌΡƒΡΠΎΡ€β€. Π­Ρ‚ΠΈ Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ Π²ΠΈΠ΄Π½Ρ‹ Π½ΠΈ ΠΎΠ΄Π½ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ.

Postgres: bloat, pg_repack ΠΈ deferred constraints

Π’ Postgres сущСствуСт ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ VACUUM, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²Ρ‹Ρ‡ΠΈΡ‰Π°Π΅Ρ‚ Π½Π΅Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ вСрсии ΠΈ освобоТдаСт мСсто для Π½ΠΎΠ²Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…. Но Ссли ΠΎΠ½ настроСн Π½Π΅ достаточно агрСссивно ΠΈΠ»ΠΈ занят Ρ€Π°Π±ΠΎΡ‚ΠΎΠΉ Π² Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ…, Ρ‚ΠΎ β€œΠΌΡƒΡΠΎΡ€Π½Ρ‹Π΅ данныС” ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ, ΠΈ Π½Π°ΠΌ приходится ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ страницы для Π½ΠΎΠ²Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ….

Π’Π°ΠΊ Π² нашСм ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π² ΠΊΠ°ΠΊΠΎΠΉ-Ρ‚ΠΎ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Π° Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΡΡ‚ΠΎΡΡ‚ΡŒ ΠΈΠ· Ρ‡Π΅Ρ‚Ρ‹Ρ€Ρ‘Ρ… страниц, Π½ΠΎ ΠΆΠΈΠ²Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ… Π² Π½Π΅ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π°. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅, ΠΏΡ€ΠΈ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠΈ ΠΊ Ρ‚Π°Π±Π»ΠΈΡ†Π΅ ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ Π²Ρ‹Ρ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ Π³ΠΎΡ€Π°Π·Π΄ΠΎ большС Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‡Π΅ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ.

Postgres: bloat, pg_repack ΠΈ deferred constraints

Π”Π°ΠΆΠ΅ Ссли сСйчас VACUUM ΡƒΠ΄Π°Π»ΠΈΡ‚ всС Π½Π΅Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ вСрсии строк, ситуация Π½Π΅ ΡƒΠ»ΡƒΡ‡ΡˆΠΈΡ‚ΡΡ ΠΊΠ°Ρ€Π΄ΠΈΠ½Π°Π»ΡŒΠ½ΠΎ. Π£ нас появится свободноС мСсто Π² страницах ΠΈΠ»ΠΈ Π΄Π°ΠΆΠ΅ Ρ†Π΅Π»Ρ‹Π΅ страницы для Π½ΠΎΠ²Ρ‹Ρ… строк, Π½ΠΎ ΠΌΡ‹ ΠΏΠΎ-ΠΏΡ€Π΅ΠΆΠ½Π΅ΠΌΡƒ Π±ΡƒΠ΄Π΅ΠΌ Π²Ρ‹Ρ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ большС Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‡Π΅ΠΌ Π½ΡƒΠΆΠ½ΠΎ.
ΠšΡΡ‚Π°Ρ‚ΠΈ, Ссли Π±Ρ‹ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ пустая страница (вторая Π² нашСм ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅) оказалась Π² ΠΊΠΎΠ½Ρ†Π΅ Ρ„Π°ΠΉΠ»Π°, Ρ‚ΠΎ VACUUM смог Π±Ρ‹ Π΅Ρ‘ ΠΎΠ±Ρ€Π΅Π·Π°Ρ‚ΡŒ. Но сСйчас ΠΎΠ½Π° находится посСрСдинС, поэтому ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ с Π½Π΅ΠΉ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ получится.

Postgres: bloat, pg_repack ΠΈ deferred constraints

Когда количСство Ρ‚Π°ΠΊΠΈΡ… пустых ΠΈΠ»ΠΈ сильно разряТСнных страниц становится большим, Ρ‡Ρ‚ΠΎ ΠΈ называСтся bloat, это Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ ΡΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒΡΡ Π½Π° ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ.

Всё описанноС Π²Ρ‹ΡˆΠ΅ β€” ΠΌΠ΅Ρ…Π°Π½ΠΈΠΊΠ° возникновСния bloat Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ…. Π’ индСксах это происходит ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Π°ΠΊ ΠΆΠ΅.

А Π΅ΡΡ‚ΡŒ Π»ΠΈ Ρƒ мСня bloat?

Π•ΡΡ‚ΡŒ нСсколько способов, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ, Π΅ΡΡ‚ΡŒ Π»ΠΈ Ρƒ вас bloat. ИдСя ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ β€” использованиС Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅ΠΉ статистики Postgres, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ содСрТится ΠΏΡ€ΠΈΠ±Π»ΠΈΠ·ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ информация ΠΎ количСствС строк Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ…, количСствС β€œΠΆΠΈΠ²Ρ‹Ρ…β€ строк ΠΈ ΠΏΡ€. Π’ ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ мноТСство Π²Π°Ρ€ΠΈΠ°Ρ†ΠΈΠΉ ΡƒΠΆΠ΅ Π³ΠΎΡ‚ΠΎΠ²Ρ‹Ρ… скриптов. ΠœΡ‹ Π·Π° основу взяли скрипт ΠΎΡ‚ PostgreSQL Experts, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΡ†Π΅Π½ΠΈΡ‚ΡŒ bloat Ρ‚Π°Π±Π»ΠΈΡ† вмСстС с toast ΠΈ bloat btree-индСксов. По Π½Π°ΡˆΠ΅ΠΌΡƒ ΠΎΠΏΡ‹Ρ‚Ρƒ Π΅Π³ΠΎ ΠΏΠΎΠ³Ρ€Π΅ΡˆΠ½ΠΎΡΡ‚ΡŒ составляСт 10-20%.

Π”Ρ€ΡƒΠ³ΠΎΠΉ способ β€” ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ pgstattuple, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡ‚ΡŒ Π·Π°Π³Π»ΡΠ½ΡƒΡ‚ΡŒ Π²Π½ΡƒΡ‚Ρ€ΡŒ страниц ΠΈ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΊΠ°ΠΊ ΠΎΡ†Π΅Π½ΠΎΡ‡Π½ΠΎΠ΅, Ρ‚Π°ΠΊ ΠΈ Ρ‚ΠΎΡ‡Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ bloat. Но Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ случаС придСтся ΠΏΡ€ΠΎΡΠΊΠ°Π½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ всю Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ.

НСбольшоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ bloat, Π΄ΠΎ 20%, ΠΌΡ‹ считаСм ΠΏΡ€ΠΈΠ΅ΠΌΠ»Π΅ΠΌΡ‹ΠΌ. Π•Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ Π°Π½Π°Π»ΠΎΠ³ fillfactor для Ρ‚Π°Π±Π»ΠΈΡ† ΠΈ индСксов. ΠŸΡ€ΠΈ 50% ΠΈ Π²Ρ‹ΡˆΠ΅ ΠΌΠΎΠ³ΡƒΡ‚ Π½Π°Ρ‡Π°Ρ‚ΡŒΡΡ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒΡŽ.

Бпособы Π±ΠΎΡ€ΡŒΠ±Ρ‹ с bloat

Π’ Postgres Π΅ΡΡ‚ΡŒ нСсколько способов Π±ΠΎΡ€ΡŒΠ±Ρ‹ с bloat β€œΠΈΠ· коробки”, ΠΎΠ΄Π½Π°ΠΊΠΎ ΠΎΠ½ΠΈ Π΄Π°Π»Π΅ΠΊΠΎ Π½Π΅ всСгда ΠΈ Π½Π΅ всСм ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΠ΄ΠΎΠΉΡ‚ΠΈ.

ΠΠ°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ AUTOVACUUM, Ρ‡Ρ‚ΠΎΠ±Ρ‹ bloat Π½Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π». А Ссли Ρ‚ΠΎΡ‡Π½Π΅Π΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ½ дСрТался Π½Π° ΠΏΡ€ΠΈΠ΅ΠΌΠ»Π΅ΠΌΠΎΠΌ для вас ΡƒΡ€ΠΎΠ²Π½Π΅. ΠšΠ°ΠΆΠ΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ это β€œΠΊΠ°ΠΏΠΈΡ‚Π°Π½ΡΠΊΠΈΠΉβ€ совСт, Π½ΠΎ Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ этого Π½Π΅ всСгда Π»Π΅Π³ΠΊΠΎ Π΄ΠΎΡΡ‚ΠΈΠ³Π½ΡƒΡ‚ΡŒ. НапримСр, Ρƒ вас ΠΈΠ΄Ρ‘Ρ‚ активная Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° с рСгулярным ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ схСмы Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ»ΠΈ происходит какая-Ρ‚ΠΎ миграция Π΄Π°Π½Π½Ρ‹Ρ…. Как слСдствиС, ваш ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ часто ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ ΠΈ, ΠΊΠ°ΠΊ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, ΠΎΠ½ Π±Ρ‹Π²Π°Π΅Ρ‚ Ρ€Π°Π·Π½Ρ‹ΠΌ для Ρ€Π°Π·Π½Ρ‹Ρ… Ρ‚Π°Π±Π»ΠΈΡ†. Π—Π½Π°Ρ‡ΠΈΡ‚, Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ постоянно Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Π½Π° ΠΎΠΏΠ΅Ρ€Π΅ΠΆΠ΅Π½ΠΈΠ΅ ΠΈ ΠΏΠΎΠ΄ΡΡ‚Ρ€Π°ΠΈΠ²Π°Ρ‚ΡŒ AUTOVACUUM ΠΏΠΎΠ΄ ΠΌΠ΅Π½ΡΡŽΡ‰ΠΈΠΉΡΡ ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. Но ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это нСпросто.

Π”Ρ€ΡƒΠ³ΠΎΠΉ распространённой ΠΏΡ€ΠΈΡ‡ΠΈΠ½ΠΎΠΉ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ AUTOVACUUM Π½Π΅ успСваСт ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹, являСтся Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Π΅ΠΌΡƒ Π²Ρ‹Ρ‡ΠΈΡ‰Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ·-Π·Π° Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΈ доступны этим транзакциям. РСкомСндация здСсь Ρ‚Π°ΠΊΠΆΠ΅ ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½Π° – ΠΈΠ·Π±Π°Π²ΠΈΡ‚ΡŒΡΡ ΠΎΡ‚ β€œΠ²ΠΈΡΡΡ‰ΠΈΡ…β€ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΉ ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ врСмя Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Ρ… Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΉ. Но Ссли Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Π½Π° вашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ – это Π³ΠΈΠ±Ρ€ΠΈΠ΄ OLAP ΠΈ OLTP, Ρ‚ΠΎ Ρƒ вас ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΊΠ°ΠΊ мноТСство частых ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ ΠΈ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΡ… запросов, Ρ‚Π°ΠΊ ΠΈ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ – Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, построСниС ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π»ΠΈΠ±ΠΎ ΠΎΡ‚Ρ‡Π΅Ρ‚Π°. Π’ Ρ‚Π°ΠΊΠΎΠΉ ситуации стоит Π·Π°Π΄ΡƒΠΌΠ°Ρ‚ΡŒΡΡ ΠΎ разнСсСнии Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ Π½Π° Ρ€Π°Π·Π½Ρ‹Π΅ Π±Π°Π·Ρ‹, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ провСсти Π±ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΠ½ΠΊΡƒΡŽ настройку ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΠ· Π½ΠΈΡ….

Π•Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ – Π΄Π°ΠΆΠ΅ Ссли ΠΏΡ€ΠΎΡ„ΠΈΠ»ΡŒ ΠΎΠ΄Π½ΠΎΡ€ΠΎΠ΄Π½Ρ‹ΠΉ, Π½ΠΎ Π‘Π” находится ΠΏΠΎΠ΄ ΠΎΡ‡Π΅Π½ΡŒ высокой Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΎΠΉ, Ρ‚ΠΎ Π΄Π°ΠΆΠ΅ максимально агрСссивный AUTOVACUUM ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ ΡΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒΡΡ, ΠΈ bloat Π±ΡƒΠ΄Π΅Ρ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Ρ‚ΡŒ. ΠœΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ (Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ΅ Π»ΠΈΠ±ΠΎ Π³ΠΎΡ€ΠΈΠ·ΠΎΠ½Ρ‚Π°Π»ΡŒΠ½ΠΎΠ΅) – СдинствСнноС Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅.

Как ΠΆΠ΅ Π±Ρ‹Ρ‚ΡŒ Π² ситуации, ΠΊΠΎΠ³Π΄Π° AUTOVACUUM Π²Ρ‹ настроили, Π½ΠΎ bloat ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅Ρ‚ расти.

Команда VACUUM FULL пСрСстраиваСт содСрТимоС Ρ‚Π°Π±Π»ΠΈΡ† ΠΈ индСксов ΠΈ оставляСт Π² Π½ΠΈΡ… Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅. Для устранСния bloat ΠΎΠ½Π° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ идСально, Π½ΠΎ Π²ΠΎ врСмя Π΅Ρ‘ выполнСния захватываСтся эксклюзивная Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ (AccessExclusiveLock), которая Π½Π΅ позволят Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ запросы ΠΊ этой Ρ‚Π°Π±Π»ΠΈΡ†Π΅, Π΄Π°ΠΆΠ΅ select-Ρ‹. Если Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ΡŒ сСбС остановку вашСго сСрвиса ΠΈΠ»ΠΈ Π΅Π³ΠΎ части Π½Π° ΠΊΠ°ΠΊΠΎΠ΅-Ρ‚ΠΎ врСмя (ΠΎΡ‚ дСсятков ΠΌΠΈΠ½ΡƒΡ‚ Π΄ΠΎ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… часов Π² зависимости ΠΎΡ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π‘Π” ΠΈ вашСго ΠΆΠ΅Π»Π΅Π·Π°), Ρ‚ΠΎ этот Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ – Π»ΡƒΡ‡ΡˆΠΈΠΉ. ΠœΡ‹, ΠΊ соТалСнию, Π½Π΅ успСваСм ΠΏΡ€ΠΎΠ³Π½Π°Ρ‚ΡŒ VACUUM FULL Π·Π° врСмя Π·Π°ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ maintenance, поэтому Ρ‚Π°ΠΊΠΎΠΉ способ Π½Π°ΠΌ Π½Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚.

Команда CLUSTER Ρ‚Π°ΠΊ ΠΆΠ΅ пСрСстраиваСт содСрТимоС Ρ‚Π°Π±Π»ΠΈΡ†, ΠΊΠ°ΠΊ ΠΈ VACUUM FULL, ΠΏΡ€ΠΈ этом позволяСт ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ индСкс, согласно ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π΄Π°Π½Π½Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ физичСски упорядочСны Π½Π° дискС (Π½ΠΎ Π² Π±ΡƒΠ΄ΡƒΡ‰Π΅ΠΌ для Π½ΠΎΠ²Ρ‹Ρ… строк порядок Π½Π΅ гарантируСтся). Π’ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹Ρ… ситуациях это нСплохая оптимизация для ряда запросов – с Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ΠΌ Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… записСй ΠΏΠΎ индСксу. НСдостаток Ρƒ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Ρ‚ΠΎΡ‚ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ Ρƒ VACUUM FULL – ΠΎΠ½Π° Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Π²ΠΎ врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹.

Команда REINDEX ΠΏΠΎΡ…ΠΎΠΆΠ° Π½Π° Π΄Π²Π΅ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠ΅, Π½ΠΎ выполняСт пСрСстроСниС ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ индСкса ΠΈΠ»ΠΈ всСх индСксов Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. Π‘Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ Ρ‡ΡƒΡ‚ΡŒ слабСС: ShareLock Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ (ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ модификациям, Π½ΠΎ позволяСт Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ select) ΠΈ AccessExclusiveLock Π½Π° пСрСстраиваСмый индСкс (Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ запросы с использованиСм этого индСкса). Однако Π² 12-ΠΉ вСрсии Postgres появился ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ CONCURRENTLY, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт ΠΏΠ΅Ρ€Π΅ΡΡ‚Ρ€Π°ΠΈΠ²Π°Ρ‚ΡŒ индСкс, Π½Π΅ блокируя ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠ΅ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅, ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΈΠ»ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ записСй.

Π’ Π±ΠΎΠ»Π΅Π΅ Ρ€Π°Π½Π½ΠΈΡ… вСрсиях Postgres ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, схоТСго с REINDEX CONCURRENTLY, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ CREATE INDEX CONCURRENTLY. Он позволяСт ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ индСкс Π±Π΅Π· строгой Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ (ShareUpdateExclusiveLock, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π΅ ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹ΠΌ запросам), Π·Π°Ρ‚Π΅ΠΌ ΠΏΠΎΠ΄ΠΌΠ΅Π½ΠΈΡ‚ΡŒ старый индСкс Π½Π° Π½ΠΎΠ²Ρ‹ΠΉ ΠΈ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ старый индСкс. Π­Ρ‚ΠΎ позволяСт ΡƒΡΡ‚Ρ€Π°Π½ΠΈΡ‚ΡŒ bloat индСксов, Π½Π΅ мСшая Ρ€Π°Π±ΠΎΡ‚Π΅ вашСго прилоТСния. Π’Π°ΠΆΠ½ΠΎ ΡƒΡ‡Π΅ΡΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈ пСрСстроСнии индСксов Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Π½Π° Π΄ΠΈΡΠΊΠΎΠ²ΡƒΡŽ подсистСму.

Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ссли для индСксов Π΅ΡΡ‚ΡŒ способы для устранСния bloat β€œΠ½Π° Π³ΠΎΡ€ΡΡ‡ΡƒΡŽβ€, Ρ‚ΠΎ для Ρ‚Π°Π±Π»ΠΈΡ† ΠΈΡ… Π½Π΅Ρ‚. Π’ΡƒΡ‚ Π² Π΄Π΅Π»ΠΎ Π²ΡΡ‚ΡƒΠΏΠ°ΡŽΡ‚ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ внСшниС Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ: pg_repack (Ρ€Π°Π½Π΅Π΅ pg_reorg), pgcompact, pgcompacttable ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅. Π’ Ρ€Π°ΠΌΠΊΠ°Ρ… этой ΡΡ‚Π°Ρ‚ΡŒΠΈ я Π½Π΅ Π±ΡƒΠ΄Ρƒ ΠΈΡ… ΡΡ€Π°Π²Π½ΠΈΠ²Π°Ρ‚ΡŒ ΠΈ расскаТу Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΎ pg_repack, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ послС Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π΄ΠΎΡ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Ρƒ сСбя.

Как Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ pg_repack

Postgres: bloat, pg_repack ΠΈ deferred constraints
Допустим, Ρƒ нас Π΅ΡΡ‚ΡŒ Π²ΠΏΠΎΠ»Π½Π΅ сСбС обычная Ρ‚Π°Π±Π»ΠΈΡ†Π° – с индСксами, ограничСниями ΠΈ, ΠΊ соТалСнию, с bloat. ΠŸΠ΅Ρ€Π²Ρ‹ΠΌ шагом pg_repack создаёт Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ…Ρ€Π°Π½ΠΈΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΠ±ΠΎ всСх измСнСниях Π²ΠΎ врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹. Π’Ρ€ΠΈΠ³Π³Π΅Ρ€ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π΅ΠΏΠ»ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ эти измСнСния Π½Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ insert, update ΠΈ delete. Π—Π°Ρ‚Π΅ΠΌ создаётся Ρ‚Π°Π±Π»ΠΈΡ†Π°, аналогичная исходной ΠΏΠΎ структурС, Π½ΠΎ Π±Π΅Π· индСксов ΠΈ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π·Π°ΠΌΠ΅Π΄Π»ΡΡ‚ΡŒ процСсс вставки Π΄Π°Π½Π½Ρ‹Ρ….

Π”Π°Π»Π΅Π΅ pg_repack пСрСносит Π² Π½ΠΎΠ²ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ· старой, автоматичСски Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΡƒΡ всС Π½Π΅Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅ строки, Π° Π·Π°Ρ‚Π΅ΠΌ создаёт индСксы для Π½ΠΎΠ²ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. Π—Π° врСмя выполнСния всСх этих ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ Π² Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Π΅ Π½Π°ΠΊΠ°ΠΏΠ»ΠΈΠ²Π°ΡŽΡ‚ΡΡ измСнСния.

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ шаг β€” пСрСнСсти измСнСния Π² Π½ΠΎΠ²ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ. ΠŸΠ΅Ρ€Π΅Π½ΠΎΡ выполняСтся Π² нСсколько ΠΈΡ‚Π΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΈ ΠΊΠΎΠ³Π΄Π° Π² Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Π΅ остаётся ΠΌΠ΅Π½Π΅Π΅ 20 записСй, pg_repack Π·Π°Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΡΡ‚Ρ€ΠΎΠ³ΡƒΡŽ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΡƒ, пСрСносит послСдниС Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ подмСняСт ΡΡ‚Π°Ρ€ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Π½Π° Π½ΠΎΠ²ΡƒΡŽ Π² систСмных Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ… Postgres. Π­Ρ‚ΠΎ СдинствСнный ΠΈ ΠΎΡ‡Π΅Π½ΡŒ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΠΈΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ Π½Π΅ смоТСтС Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Ρ‚Π°Π±Π»ΠΈΡ†Π΅ΠΉ. ПослС этого старая Ρ‚Π°Π±Π»ΠΈΡ†Π° ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Π° с Π»ΠΎΠ³Π°ΠΌΠΈ ΡƒΠ΄Π°Π»ΡΡŽΡ‚ΡΡ ΠΈ Π² Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмС освобоТдаСтся мСсто. ΠŸΡ€ΠΎΡ†Π΅ΡΡ Π·Π°Π²Π΅Ρ€ΡˆΡ‘Π½.

Π’ Ρ‚Π΅ΠΎΡ€ΠΈΠΈ всё выглядит ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ, Ρ‡Ρ‚ΠΎ ΠΆΠ΅ Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅? ΠœΡ‹ протСстировали pg_repack Π±Π΅Π· Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΈ ΠΏΠΎΠ΄ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΎΠΉ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠ»ΠΈ Π΅Π³ΠΎ Ρ€Π°Π±ΠΎΡ‚Ρƒ Π² случаС ΠΏΡ€Π΅ΠΆΠ΄Π΅Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ остановки (ΠΏΡ€ΠΎΡ‰Π΅ говоря, ΠΏΠΎ Ctrl+C). ВсС тСсты Π±Ρ‹Π»ΠΈ ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ.

ΠœΡ‹ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΠ»ΠΈΡΡŒ Π½Π° ΠΏΡ€ΠΎΠ΄ β€” ΠΈ Ρ‚ΡƒΡ‚ всё пошло Π½Π΅ Ρ‚Π°ΠΊ, ΠΊΠ°ΠΊ ΠΌΡ‹ ΠΎΠΆΠΈΠ΄Π°Π»ΠΈ.

ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ Π±Π»ΠΈΠ½ Π½Π° ΠΏΡ€ΠΎΠ΄Π΅

На ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΆΠ΅ кластСрС ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ ΠΎΡˆΠΈΠ±ΠΊΡƒ ΠΎ Π½Π°Ρ€ΡƒΡˆΠ΅Π½ΠΈΠΈ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ ограничСния:

$ ./pg_repack -t tablename -o id
INFO: repacking table "tablename"
ERROR: query failed: 
    ERROR: duplicate key value violates unique constraint "index_16508"
DETAIL:  Key (id, index)=(100500, 42) already exists.

Π­Ρ‚ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ ΠΈΠΌΠ΅Π»ΠΎ автосгСнСрированноС Π½Π°ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΠ΅ index_16508 – Π΅Π³ΠΎ создал pg_repack. По Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌ, входящим Π² Π΅Π³ΠΎ состав, ΠΌΡ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠ»ΠΈ β€œΠ½Π°ΡˆΠ΅β€ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π΅ΠΌΡƒ соотвСтствуСт. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° оказалось Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ это Π½Π΅ совсСм ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅, Π° ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ (deferred constraint), Ρ‚.Π΅. Π΅Π³ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° выполняСтся ΠΏΠΎΠ·ΠΆΠ΅, Ρ‡Π΅ΠΌ sql-ΠΊΠΎΠΌΠ°Π½Π΄Π°, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ Π½Π΅ΠΎΠΆΠΈΠ΄Π°Π½Π½Ρ‹ΠΌ послСдствиям.

Deferred constraints: Π·Π°Ρ‡Π΅ΠΌ Π½ΡƒΠΆΠ½Ρ‹ ΠΈ ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚

НСмного Ρ‚Π΅ΠΎΡ€ΠΈΠΈ ΠΎ deferred-ограничСниях.
Рассмотрим простой ΠΏΡ€ΠΈΠΌΠ΅Ρ€: Ρƒ нас Π΅ΡΡ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Π°-справочник Π°Π²Ρ‚ΠΎΠΌΠΎΠ±ΠΈΠ»Π΅ΠΉ с двумя Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌΠΈ – Π½Π°ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΈ порядком автомобиля Π² справочникС.
Postgres: bloat, pg_repack ΠΈ deferred constraints

create table cars
(
  name text constraint pk_cars primary key,
  ord integer not null constraint uk_cars unique
);



Допустим, Π½Π°ΠΌ понадобилось ΠΏΠΎΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΈ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Π°Π²Ρ‚ΠΎΠΌΠΎΠ±ΠΈΠ»ΠΈ мСстами. РСшСниС β€œΠ² лоб” – ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π½Π° Π²Ρ‚ΠΎΡ€ΠΎΠ΅, Π° Π²Ρ‚ΠΎΡ€ΠΎΠ΅ Π½Π° ΠΏΠ΅Ρ€Π²ΠΎΠ΅:

begin;
  update cars set ord = 2 where name = 'audi';
  update cars set ord = 1 where name = 'bmw';
commit;

Но ΠΏΡ€ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ этого ΠΊΠΎΠ΄Π° ΠΌΡ‹ ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Π½Π°Ρ€ΡƒΡˆΠ΅Π½ΠΈΠ΅ ограничСния, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ порядок Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅ ΡƒΠ½ΠΈΠΊΠ°Π»Π΅Π½:

[23305] ERROR: duplicate key value violates unique constraint β€œuk_cars”
Detail: Key (ord)=(2) already exists.

Как ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΏΠΎ-Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ? Π’Π°Ρ€ΠΈΠ°Π½Ρ‚ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ: Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Π·Π°ΠΌΠ΅Π½Ρƒ значСния Π½Π° порядок, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎ Π½Π΅ сущСствуСт Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ β€œ-1”. Π’ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ это называСтся β€œΠΎΠ±ΠΌΠ΅Π½ΠΎΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π΄Π²ΡƒΡ… ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… Ρ‡Π΅Ρ€Π΅Π· Ρ‚Ρ€Π΅Ρ‚ΡŒΡŽβ€. ЕдинствСнный нСдостаток этого ΠΌΠ΅Ρ‚ΠΎΠ΄Π° – Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ update.

Π’Π°Ρ€ΠΈΠ°Π½Ρ‚ Π²Ρ‚ΠΎΡ€ΠΎΠΉ: ΠΏΠ΅Ρ€Π΅ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для значСния порядка Ρ‚ΠΈΠΏ Π΄Π°Π½Π½Ρ‹Ρ… с ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ вмСсто Ρ†Π΅Π»Ρ‹Ρ… чисСл. Π’ΠΎΠ³Π΄Π° ΠΏΡ€ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ значСния с 1, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½Π° 2.5 пСрвая запись автоматичСски β€œΠ²ΡΡ‚Π°Π½Π΅Ρ‚β€ ΠΌΠ΅ΠΆΠ΄Ρƒ Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΈ Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΉ. Π­Ρ‚ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰Π΅Π΅, Π½ΠΎ Π΅ΡΡ‚ΡŒ Π΄Π²Π° ограничСния. Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, ΠΎΠ½ΠΎ Π½Π΅ ΠΏΠΎΠ΄ΠΎΠΉΠ΄Π΅Ρ‚ Π²Π°ΠΌ, Ссли Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π³Π΄Π΅-Ρ‚ΠΎ Π² интСрфСйсС. Π’ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, Π² зависимости ΠΎΡ‚ точности Ρ‚ΠΈΠΏΠ° Π΄Π°Π½Π½Ρ‹Ρ… Π²Ρ‹ Π±ΡƒΠ΄Π΅Ρ‚Π΅ ΠΈΠΌΠ΅Ρ‚ΡŒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½Π½ΠΎΠ΅ количСство Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹Ρ… вставок Π΄ΠΎ провСдСния пСрСрасчёта Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ всСх записСй.

Π’Π°Ρ€ΠΈΠ°Π½Ρ‚ Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ: ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΠ»ΠΎΡΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΊΠΎΠΌΠΌΠΈΡ‚Π°:

create table cars
(
  name text constraint pk_cars primary key,
  ord integer not null constraint uk_cars unique deferrable initially deferred
);

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π»ΠΎΠ³ΠΈΠΊΠ° нашСго ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ запроса Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΊ ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρƒ ΠΊΠΎΠΌΠΌΠΈΡ‚Π° всС значСния ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹, Ρ‚ΠΎ ΠΎΠ½ выполнится ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ.

РассмотрСнный Π²Ρ‹ΡˆΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ, ΠΎΡ‡Π΅Π½ΡŒ синтСтичСский, Π½ΠΎ идСю раскрываСт. Π’ нашСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ограничСния для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π»ΠΎΠ³ΠΈΠΊΠΈ, которая ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ΠΎΠ² ΠΏΡ€ΠΈ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ с ΠΎΠ±Ρ‰ΠΈΠΌΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ-Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Π°ΠΌΠΈ Π½Π° доскС. ИспользованиС Ρ‚Π°ΠΊΠΈΡ… ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ позволяСт Π½Π°ΠΌ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠΊΠ»Π°Π΄Π½ΠΎΠΉ ΠΊΠΎΠ΄ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΡ‰Π΅.

Π’ Ρ†Π΅Π»ΠΎΠΌ, Π² зависимости ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° ограничСния Π² Postgres сущСствуСт Ρ‚Ρ€ΠΈ уровня гранулярности ΠΈΡ… ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ: ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ строки, Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΠΈ выраТСния.
Postgres: bloat, pg_repack ΠΈ deferred constraints
Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: begriffs

CHECK ΠΈ NOT NULL всСгда ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡŽΡ‚ΡΡ Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ строки, для ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ, ΠΊΠ°ΠΊ Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹, Π΅ΡΡ‚ΡŒ Ρ€Π°Π·Π½Ρ‹Π΅ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Ρ‹. ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ здСсь.

Если ΠΊΡ€Π°Ρ‚ΠΊΠΎ ΠΏΠΎΠ΄Ρ‹Ρ‚ΠΎΠΆΠΈΡ‚ΡŒ, Ρ‚ΠΎ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ограничСния Π² рядС ситуаций Π΄Π°ΡŽΡ‚ Π±ΠΎΠ»Π΅Π΅ понятный для чтСния ΠΊΠΎΠ΄ ΠΈ мСньшСС количСство ΠΊΠΎΠΌΠ°Π½Π΄. Однако Π·Π° это приходится ΠΏΠ»Π°Ρ‚ΠΈΡ‚ΡŒ услоТнСниСм процСсса Π΄Π΅Π±Π°Π³Π°, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΠΎΠΌΠ΅Π½Ρ‚ возникновСния ошибки ΠΈ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ ΠΎ Π½Π΅ΠΉ ΡƒΠ·Π½Π°Ρ‘Ρ‚Π΅, разнСсСны Π²ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. Π•Ρ‰Ρ‘ ΠΎΠ΄Π½Π° возмоТная ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° связана с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Ρ‰ΠΈΠΊ Π½Π΅ всСгда ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠ»Π°Π½, Ссли Π² запросС участвуСт ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅.

Π”ΠΎΡ€Π°Π±ΠΎΡ‚ΠΊΠ° pg_repack

ΠœΡ‹ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Π»ΠΈΡΡŒ с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ограничСния, Π½ΠΎ ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ связаны с нашСй ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ? Вспомним ΠΎΡˆΠΈΠ±ΠΊΡƒ, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ Ρ€Π°Π½Π΅Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ:

$ ./pg_repack -t tablename -o id
INFO: repacking table "tablename"
ERROR: query failed: 
    ERROR: duplicate key value violates unique constraint "index_16508"
DETAIL:  Key (id, index)=(100500, 42) already exists.

Она Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ копирования Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π² Π½ΠΎΠ²ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ. Π­Ρ‚ΠΎ выглядит странно, Ρ‚.ΠΊ. Π΄Π°Π½Π½Ρ‹Π΅ Π² Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Π΅ коммитятся вмСстС с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ исходной Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. Если ΠΎΠ½ΠΈ ΡƒΠ΄ΠΎΠ²Π»Π΅Ρ‚Π²ΠΎΡ€ΡΡŽΡ‚ ограничСниям исходной Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹, Ρ‚ΠΎ ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π½Π°Ρ€ΡƒΡˆΠ°Ρ‚ΡŒ Ρ‚Π΅ ΠΆΠ΅ самыС ограничСния Π² Π½ΠΎΠ²ΠΎΠΉ?

Как оказалось, ΠΊΠΎΡ€Π΅Π½ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ таится Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌ шагС Ρ€Π°Π±ΠΎΡ‚Ρ‹ pg_repack, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ индСксы, Π½ΠΎ Π½Π΅ ограничСния: Π² старой Ρ‚Π°Π±Π»ΠΈΡ†Π΅ Π±Ρ‹Π»ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅, Π° Π² Π½ΠΎΠ²ΠΎΠΉ вмСсто Π½Π΅Π³ΠΎ создался ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ индСкс.

Postgres: bloat, pg_repack ΠΈ deferred constraints

Π’ΡƒΡ‚ Π²Π°ΠΆΠ½ΠΎ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Ссли ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ΅, Π° Π½Π΅ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅, Ρ‚ΠΎ созданный вмСсто Π½Π΅Π³ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ индСкс равносилСн этому ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡŽ, Ρ‚.ΠΊ. ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ ограничСния Π² Postgres Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‚ΡΡ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ создания ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ индСкса. Но Π² случаС с ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΌ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½Π΅ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ индСкс Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΌ ΠΈ всСгда провСряСтся Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ выполнСния sql-ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹.

Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΡΡƒΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² β€œΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΡΡ‚ΠΈβ€ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ: Π² исходной Ρ‚Π°Π±Π»ΠΈΡ†Π΅ ΠΎΠ½Π° происходит Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΊΠΎΠΌΠΌΠΈΡ‚Π°, Π° Π² Π½ΠΎΠ²ΠΎΠΉ – Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ выполнСния sql-ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹. Π—Π½Π°Ρ‡ΠΈΡ‚ Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΠ»ΠΈΡΡŒ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ Π² ΠΎΠ±ΠΎΠΈΡ… случаях: Π»ΠΈΠ±ΠΎ всСгда ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎ, Π»ΠΈΠ±ΠΎ всСгда сразу ΠΆΠ΅.

Π˜Ρ‚Π°ΠΊ, ΠΊΠ°ΠΊΠΈΠ΅ ΠΈΠ΄Π΅ΠΈ Ρƒ нас Π±Ρ‹Π»ΠΈ.

Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ индСкс, Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ΠΉ deferred

ΠŸΠ΅Ρ€Π²Π°Ρ идСя – Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ ΠΎΠ±Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ immediate. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΡ€ΠΎΠ΄ΠΈΡ‚ΡŒ нСсколько false positive срабатываний ограничСния, Π½ΠΎ Ссли ΠΈΡ… Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ, Ρ‚ΠΎ это Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΡ‚Ρ€Π°Π·ΠΈΡ‚ΡŒΡΡ Π½Π° Ρ€Π°Π±ΠΎΡ‚Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ для Π½ΠΈΡ… Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚Ρ‹ – Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½Π°Ρ ситуация. Они происходят, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠΎΠ³Π΄Π° Π΄Π²Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚, ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ Π½Π΅ успСваСт ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚ ΡƒΠΆΠ΅ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ Π½Π° Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ. Π’ Ρ‚Π°ΠΊΠΎΠΉ ситуации сСрвСр ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π²Ρ‚ΠΎΡ€ΠΎΠΌΡƒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ ΠΎΡ‚ΠΊΠ°Π·ΠΎΠΌ, Π° Π΅Π³ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ ΠΎΡ‚ΠΊΠ°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ измСнСния ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅Ρ‚ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚. Π§ΡƒΡ‚ΡŒ ΠΏΠΎΠ·ΠΆΠ΅, ΠΊΠΎΠ³Π΄Π° ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅, Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ, Ρ‡Ρ‚ΠΎ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚ большС Π½Π΅ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½, ΠΈ смоТСт ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΠΈΡ‚ΡŒ своё дСйствиС.

Postgres: bloat, pg_repack ΠΈ deferred constraints

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π±Ρ‹Π»ΠΈ всСгда Π² Π½Π΅ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅, ΠΌΡ‹ создали Π½ΠΎΠ²Ρ‹ΠΉ индСкс, Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ΠΉ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΌΡƒ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠΌΡƒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡŽ:

CREATE UNIQUE INDEX CONCURRENTLY uk_tablename__immediate ON tablename (id, index);
-- run pg_repack
DROP INDEX CONCURRENTLY uk_tablename__immediate;

На тСстовом ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠΈ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ всСго нСсколько ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌΡ‹Ρ… ошибок. УспСх! Π‘Π½ΠΎΠ²Π° запустили pg_repack Π½Π° ΠΏΡ€ΠΎΠ΄Π΅ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ 5 ошибок Π½Π° ΠΏΠ΅Ρ€Π²ΠΎΠΌ кластСрС Π·Π° час Ρ€Π°Π±ΠΎΡ‚Ρ‹. Π­Ρ‚ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ»Π΅ΠΌΡ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚. Однако ΡƒΠΆΠ΅ Π½Π° Π²Ρ‚ΠΎΡ€ΠΎΠΌ кластСрС количСство ошибок ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ»ΠΎΡΡŒ Π² Ρ€Π°Π·Ρ‹ ΠΈ Π½Π°ΠΌ ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ pg_repack.

ΠŸΠΎΡ‡Π΅ΠΌΡƒ Ρ‚Π°ΠΊ ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ? Π’Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒ возникновСния ошибки зависит ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ с ΠΎΠ΄Π½ΠΈΠΌΠΈ ΠΈ Ρ‚Π΅ΠΌΠΈ ΠΆΠ΅ Π²ΠΈΠ΄ΠΆΠ΅Ρ‚Π°ΠΌΠΈ. Будя ΠΏΠΎ всСму, Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚ с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ, хранящихся Π½Π° ΠΏΠ΅Ρ€Π²ΠΎΠΌ кластСрС, Π±Ρ‹Π»ΠΎ Π³ΠΎΡ€Π°Π·Π΄ΠΎ мСньшС ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½Ρ‹Ρ… ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, Ρ‡Π΅ΠΌ Π½Π° ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ…, Ρ‚.Π΅. Π½Π°ΠΌ просто β€œΠΏΠΎΠ²Π΅Π·Π»ΠΎβ€.

ИдСя Π½Π΅ сработала. Π’ Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΌΡ‹ Π²ΠΈΠ΄Π΅Π»ΠΈ Π΄Π²Π° Π΄Ρ€ΡƒΠ³ΠΈΡ… Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ: ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ наш ΠΏΡ€ΠΈΠΊΠ»Π°Π΄Π½ΠΎΠΉ ΠΊΠΎΠ΄, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ, ΠΈΠ»ΠΈ β€œΠ½Π°ΡƒΡ‡ΠΈΡ‚ΡŒβ€ pg_repack Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Π½ΠΈΠΌΠΈ. ΠœΡ‹ Π²Ρ‹Π±Ρ€Π°Π»ΠΈ Π²Ρ‚ΠΎΡ€ΠΎΠΉ.

Π—Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ индСксы Π² Π½ΠΎΠ²ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Π΅ Π½Π° ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ограничСния ΠΈΠ· исходной Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹

ЦСль Π΄ΠΎΡ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π±Ρ‹Π»Π° ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½Π° – Ссли исходная Ρ‚Π°Π±Π»ΠΈΡ†Π° ΠΈΠΌΠ΅Π΅Ρ‚ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎ для Π½ΠΎΠ²ΠΎΠΉ Π½ΡƒΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΎΠ΅ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅, Π° Π½Π΅ индСкс.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡΡ‚ΡŒ наши измСнСния, ΠΌΡ‹ написали простой тСст:

  • Ρ‚Π°Π±Π»ΠΈΡ†Π° с ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΌ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ΠΌ ΠΈ ΠΎΠ΄Π½ΠΎΠΉ записью;
  • вставляСм Π² Ρ†ΠΈΠΊΠ»Π΅ Π΄Π°Π½Π½Ρ‹Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ΡƒΡŽΡ‚ с ΠΈΠΌΠ΅ΡŽΡ‰Π΅ΠΉΡΡ записью;
  • Π΄Π΅Π»Π°Π΅ΠΌ update – Π΄Π°Π½Π½Ρ‹Π΅ ΡƒΠΆΠ΅ Π½Π΅ ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ΡƒΡŽΡ‚;
  • ΠΊΠΎΠΌΠΌΠΈΡ‚ΠΈΠΌ измСнСния.

create table test_table
(
  id serial,
  val int,
  constraint uk_test_table__val unique (val) deferrable initially deferred 
);

INSERT INTO test_table (val) VALUES (0);
FOR i IN 1..10000 LOOP
  BEGIN
    INSERT INTO test_table VALUES (0) RETURNING id INTO v_id;
    UPDATE test_table set val = i where id = v_id;
    COMMIT;
  END;
END LOOP;

Π˜ΡΡ…ΠΎΠ΄Π½Π°Ρ вСрсия pg_repack всСгда ΠΏΠ°Π΄Π°Π»Π° Π½Π° ΠΏΠ΅Ρ€Π²ΠΎΠΌ insert, доработанная вСрсия Ρ€Π°Π±ΠΎΡ‚Π°Π»Π° Π±Π΅Π· ошибок. ΠžΡ‚Π»ΠΈΡ‡Π½ΠΎ.

Π˜Π΄Ρ‘ΠΌ Π½Π° ΠΏΡ€ΠΎΠ΄ ΠΈ снова ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΎΡˆΠΈΠ±ΠΊΡƒ Π½Π° Ρ‚ΠΎΠΉ ΠΆΠ΅ Ρ„Π°Π·Π΅ копирования Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π² Π½ΠΎΠ²ΡƒΡŽ:

$ ./pg_repack -t tablename -o id
INFO: repacking table "tablename"
ERROR: query failed: 
    ERROR: duplicate key value violates unique constraint "index_16508"
DETAIL:  Key (id, index)=(100500, 42) already exists.

ΠšΠ»Π°ΡΡΠΈΡ‡Π΅ΡΠΊΠ°Ρ ситуация: Π½Π° тСстовых окруТСниях всё Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚, Π° Π½Π° ΠΏΡ€ΠΎΠ΄Π΅ β€” Π½Π΅Ρ‚?!

APPLY_COUNT ΠΈ стык Π΄Π²ΡƒΡ… Π±Π°Ρ‚Ρ‡Π΅ΠΉ

ΠœΡ‹ Π½Π°Ρ‡Π°Π»ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠ΄ Π±ΡƒΠΊΠ²Π°Π»ΡŒΠ½ΠΎ построчно ΠΈ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ»ΠΈ Π²Π°ΠΆΠ½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚: ΠΏΠ΅Ρ€Π΅Π»ΠΈΠ²ΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π² Π½ΠΎΠ²ΡƒΡŽ происходит Π±Π°Ρ‚Ρ‡Π°ΠΌΠΈ, константа APPLY_COUNT ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π»Π° Π½Π° Ρ€Π°Π·ΠΌΠ΅Ρ€ Π±Π°Ρ‚Ρ‡Π°:

for (;;)
{
num = apply_log(connection, table, APPLY_COUNT);

if (num > MIN_TUPLES_BEFORE_SWITCH)
     continue;  /* there might be still some tuples, repeat. */
...
}

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹Π΅ исходной Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ нСсколько ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ Π½Π°Ρ€ΡƒΡˆΠΈΡ‚ΡŒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅, ΠΏΡ€ΠΈ пСрСносС ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΠΏΠ°ΡΡ‚ΡŒ Π½Π° стык Π΄Π²ΡƒΡ… Π±Π°Ρ‚Ρ‡Π΅ΠΉ – ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π° ΠΊΠΎΠΌΠ°Π½Π΄ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΊΠΎΠΌΠΌΠΈΡ‚Ρ‡ΠΈΠ½Π° Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ Π±Π°Ρ‚Ρ‡Π΅, Π° другая ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π° β€” Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ. И здСсь ΠΊΠ°ΠΊ ΠΏΠΎΠ²Π΅Π·Ρ‘Ρ‚: Ссли ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ Π±Π°Ρ‚Ρ‡Π΅ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π½Π°Ρ€ΡƒΡˆΠ°ΡŽΡ‚, Ρ‚ΠΎ всё Ρ…ΠΎΡ€ΠΎΡˆΠΎ, Π° Ссли Π½Π°Ρ€ΡƒΡˆΠ°ΡŽΡ‚ β€” происходит ошибка.

APPLY_COUNT Ρ€Π°Π²Π΅Π½ 1000 записСй, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΡΡΠ½ΡΠ΅Ρ‚, ΠΏΠΎΡ‡Π΅ΠΌΡƒ наши тСсты ΠΏΡ€ΠΎΡ…ΠΎΠ΄ΠΈΠ»ΠΈ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ – ΠΎΠ½ΠΈ Π½Π΅ ΠΏΠΎΠΊΡ€Ρ‹Π²Π°Π»ΠΈ случая β€œΡΡ‚Ρ‹ΠΊΠ° батчСй”. ΠœΡ‹ использовали Π΄Π²Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ – insert ΠΈ update, поэтому Ρ€ΠΎΠ²Π½ΠΎ 500 Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΉ ΠΏΠΎ Π΄Π²Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ всСгда ΠΏΠΎΠΌΠ΅Ρ‰Π°Π»ΠΈΡΡŒ Π² Π±Π°Ρ‚Ρ‡ ΠΈ ΠΌΡ‹ Π½Π΅ испытывали ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ. ПослС добавлСния Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ update наша ΠΏΡ€Π°Π²ΠΊΠ° пСрСстала Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ:

FOR i IN 1..10000 LOOP
  BEGIN
    INSERT INTO test_table VALUES (1) RETURNING id INTO v_id;
    UPDATE test_table set val = i where id = v_id;
    UPDATE test_table set val = i where id = v_id; -- one more update
    COMMIT;
  END;
END LOOP;

Π˜Ρ‚Π°ΠΊ, ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ Π·Π°Π΄Π°Ρ‡Π° – ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ· исходной Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ измСнялись Π² ΠΎΠ΄Π½ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, ΠΏΠΎΠΏΠ°Π΄Π°Π»ΠΈ Π² Π½ΠΎΠ²ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Ρ‚Π°ΠΊΠΆΠ΅ Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΎΠ΄Π½ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ.

ΠžΡ‚ΠΊΠ°Π· ΠΎΡ‚ Π±Π°Ρ‚Ρ‡ΠΈΠ½Π³Π°

И Ρƒ нас снова Π±Ρ‹Π»ΠΎ Π΄Π²Π° Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ. ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ: Π΄Π°Π²Π°ΠΉΡ‚Π΅ Π²ΠΎΠΎΠ±Ρ‰Π΅ откаТСмся ΠΎΡ‚ разбиСния Π½Π° Π±Π°Ρ‚Ρ‡ΠΈ ΠΈ Π±ΡƒΠ΄Π΅ΠΌ Π΄Π΅Π»Π°Ρ‚ΡŒ пСрСнос Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ΄Π½ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠ΅ΠΉ. Π’ ΠΏΠΎΠ»ΡŒΠ·Ρƒ этого Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π±Ρ‹Π»Π° Π΅Π³ΠΎ простота – Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹Π΅ измСнСния ΠΊΠΎΠ΄Π° ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ (кстати, Π² Π±ΠΎΠ»Π΅Π΅ старых вСрсиях Ρ‚ΠΎΠ³Π΄Π° Π΅Ρ‰Π΅ pg_reorg Ρ€Π°Π±ΠΎΡ‚Π°Π» ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚Π°ΠΊ). Но Π΅ΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° β€” ΠΌΡ‹ создаём Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΡŽ, Π° это, ΠΊΠ°ΠΊ Π±Ρ‹Π»ΠΎ Ρ€Π°Π½Π΅Π΅ сказано, – ΡƒΠ³Ρ€ΠΎΠ·Π° для возникновСния Π½ΠΎΠ²ΠΎΠ³ΠΎ bloat.

Π’Ρ‚ΠΎΡ€ΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ β€” Π±ΠΎΠ»Π΅Π΅ слоТноС, Π½ΠΎ, Π½Π°Π²Π΅Ρ€Π½ΠΎΠ΅, Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅: ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π² Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Π΅ столбСц с ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ Ρ‚ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, которая Π΄ΠΎΠ±Π°Π²ΠΈΠ»Π° Π΄Π°Π½Π½Ρ‹Π΅ Π² Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ. Π’ΠΎΠ³Π΄Π° ΠΏΡ€ΠΈ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΡ‹ смоТСм Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… ΠΏΠΎ этому Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Ρƒ ΠΈ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ связанныС измСнСния Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠ΅Ρ€Π΅Π½ΠΎΡΠΈΡ‚ΡŒΡΡ совмСстно. Π‘Π°Ρ‚Ρ‡ Π±ΡƒΠ΄Π΅Ρ‚ Ρ„ΠΎΡ€ΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΉ (ΠΈΠ»ΠΈ ΠΎΠ΄Π½ΠΎΠΉ большой) ΠΈ Π΅Π³ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€ Π±ΡƒΠ΄Π΅Ρ‚ Π²Π°Ρ€ΡŒΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² зависимости ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ»ΠΈ Π² этих транзакциях. Π’Π°ΠΆΠ½ΠΎ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π΄Π°Π½Π½Ρ‹Π΅ Ρ€Π°Π·Π½Ρ‹Ρ… Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΉ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ Π² Π»ΠΎΠ³-Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Π² случайном порядкС, Ρ‚ΠΎ ΡƒΠΆΠ΅ Π½Π΅ получится Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π΅Π΅ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, ΠΊΠ°ΠΊ это Π±Ρ‹Π»ΠΎ Ρ€Π°Π½ΡŒΡˆΠ΅. seqscan ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ запросС с Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠ΅ΠΉ ΠΏΠΎ tx_id – это слишком Π΄ΠΎΡ€ΠΎΠ³ΠΎ, Π½ΡƒΠΆΠ΅Π½ индСкс, Π½ΠΎ ΠΈ ΠΎΠ½ Π·Π°ΠΌΠ΅Π΄Π»ΠΈΡ‚ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΈΠ·-Π·Π° Π½Π°ΠΊΠ»Π°Π΄Π½Ρ‹Ρ… расходов Π½Π° Π΅Π³ΠΎ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅. Π’ ΠΎΠ±Ρ‰Π΅ΠΌ, ΠΊΠ°ΠΊ всСгда Π½ΡƒΠΆΠ½ΠΎ Ρ‡Π΅ΠΌ-Ρ‚ΠΎ ΠΆΠ΅Ρ€Ρ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ.

Π˜Ρ‚Π°ΠΊ, ΠΌΡ‹ Ρ€Π΅ΡˆΠΈΠ»ΠΈ Π½Π°Ρ‡Π°Ρ‚ΡŒ с ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°, ΠΊΠ°ΠΊ Π±ΠΎΠ»Π΅Π΅ простого. Для Π½Π°Ρ‡Π°Π»Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π±Ρ‹Π»ΠΎ ΠΏΠΎΠ½ΡΡ‚ΡŒ Π±ΡƒΠ΄Π΅Ρ‚ Π»ΠΈ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ транзакция Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ основной пСрСнос Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· старой Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π² Π½ΠΎΠ²ΡƒΡŽ происходит Ρ‚Π°ΠΊΠΆΠ΅ Π² ΠΎΠ΄Π½ΠΎΠΉ Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ, Ρ‚ΠΎ вопрос трансформировался Π² β€œΠ½Π°ΡΠΊΠΎΠ»ΡŒΠΊΠΎ ΠΌΡ‹ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠΌ эту Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΡŽ?” ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΠ΅Ρ€Π²ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ зависит Π² основном ΠΎΡ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Π½ΠΎΠ²ΠΎΠΉ – ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ ΠΊΠ°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ накопится Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅ Π·Π° врСмя ΠΏΠ΅Ρ€Π΅Π»ΠΈΠ²ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‚.Π΅. ΠΎΡ‚ интСнсивности Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ. ΠŸΡ€ΠΎΠ³ΠΎΠ½ pg_repack происходил Π²ΠΎ врСмя минимальной Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ Π½Π° сСрвис, ΠΈ объСм ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Π±Ρ‹Π» нСсопоставимо ΠΌΠ°Π» ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с исходным объСмом Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. ΠœΡ‹ Ρ€Π΅ΡˆΠΈΠ»ΠΈ, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡ€Π΅Π½Π΅Π±Ρ€Π΅Ρ‡ΡŒ Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ Π½ΠΎΠ²ΠΎΠΉ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ (для сравнСния усрСднСнно это 1Ρ‡ ΠΈ 2-3 ΠΌΠΈΠ½ΡƒΡ‚Ρ‹).

ЭкспСримСнты Π±Ρ‹Π»ΠΈ ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹. Запуск Π½Π° ΠΏΡ€ΠΎΠ΄Π΅ Ρ‚ΠΎΠΆΠ΅. Для наглядности – ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠ° с Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ ΠΎΠ΄Π½ΠΎΠΉ ΠΈΠ· Π±Π°Π· послС ΠΏΡ€ΠΎΠ³ΠΎΠ½Π°:

Postgres: bloat, pg_repack ΠΈ deferred constraints

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ это Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ нас ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ устроило, Ρ‚ΠΎ ΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π²Ρ‚ΠΎΡ€ΠΎΠ΅ ΠΌΡ‹ Π½Π΅ стали, Π½ΠΎ рассматриваСм Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π΅Π³ΠΎ обсуТдСния с Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ. Наши тСкущая Π΄ΠΎΡ€Π°Π±ΠΎΡ‚ΠΊΠ°, ΠΊ соТалСнию, ΠΏΠΎΠΊΠ° Π΅Ρ‰Π΅ Π½Π΅ Π³ΠΎΡ‚ΠΎΠ²Π° ΠΊ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ Ρ€Π΅ΡˆΠΈΠ»ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΌΠΈ ограничСниями, Π° для ΠΏΠΎΠ»Π½ΠΎΡ†Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ°Ρ‚Ρ‡Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ². НадССмся, Ρ‡Ρ‚ΠΎ удастся ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это Π² Π±ΡƒΠ΄ΡƒΡ‰Π΅ΠΌ.

Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Ρƒ вас Π²ΠΎΠ·Π½ΠΈΠΊ вопрос, Π·Π°Ρ‡Π΅ΠΌ ΠΌΡ‹ Π²ΠΎΠΎΠ±Ρ‰Π΅ ввязались Π² эту ΠΈΡΡ‚ΠΎΡ€ΠΈΡŽ с Π΄ΠΎΡ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ pg_repack, Π° Π½Π΅ стали, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π³ΠΎ Π°Π½Π°Π»ΠΎΠ³ΠΈ? Π’ ΠΊΠ°ΠΊΠΎΠΉ-Ρ‚ΠΎ ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΌΡ‹ Ρ‚ΠΎΠΆΠ΅ Π΄ΡƒΠΌΠ°Π»ΠΈ ΠΎΠ± этом, Π½ΠΎ ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ Π΅Π³ΠΎ использования Ρ€Π°Π½Π΅Π΅, Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ… Π±Π΅Π· ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ, ΠΌΠΎΡ‚ΠΈΠ²ΠΈΡ€ΠΎΠ²Π°Π» Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ Π² сути ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΈ ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Π΅Ρ‘. К Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ для использования Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ Ρ‚Π°ΠΊ ΠΆΠ΅ трСбуСтся врСмя Π½Π° ΠΏΡ€ΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ тСстов, поэтому ΠΌΡ‹ Ρ€Π΅ΡˆΠΈΠ»ΠΈ, Ρ‡Ρ‚ΠΎ спСрва ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ Π² Π½Π΅ΠΌ, ΠΈ Ссли ΠΏΠΎΠΉΠΌΠ΅ΠΌ, Ρ‡Ρ‚ΠΎ Π½Π΅ смоТСм ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это Π·Π° Ρ€Π°Π·ΡƒΠΌΠ½ΠΎΠ΅ врСмя, Ρ‚ΠΎ Ρ‚ΠΎΠ³Π΄Π° Π½Π°Ρ‡Π½Π΅ΠΌ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ Π°Π½Π°Π»ΠΎΠ³ΠΈ.

Π’Ρ‹Π²ΠΎΠ΄Ρ‹

Π§Ρ‚ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΠΎΠ²Π°Ρ‚ΡŒ Π½Π° основС собствСнного ΠΎΠΏΡ‹Ρ‚Π°:

  1. ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€ΡŒΡ‚Π΅ ваш bloat. На основС Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³Π° Π²Ρ‹ смоТСтС ΠΏΠΎΠ½ΡΡ‚ΡŒ, насколько Ρ…ΠΎΡ€ΠΎΡˆΠΎ настроСн autovacuum.
  2. НастраивайтС AUTOVACUUM, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ bloat Π½Π° допустимом ΡƒΡ€ΠΎΠ²Π½Π΅.
  3. Если всё ΠΆΠ΅ bloat растСт ΠΈ Π²Ρ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΅Π³ΠΎ ΠΏΠΎΠ±ΠΎΡ€ΠΎΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ срСдств β€œΠΈΠ· коробки”, Π½Π΅ Π±ΠΎΠΉΡ‚Π΅ΡΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ внСшниС Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ. Π“Π»Π°Π²Π½ΠΎΠ΅ – всС Ρ…ΠΎΡ€ΠΎΡˆΠΎ Ρ‚Π΅ΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ.
  4. НС Π±ΠΎΠΉΡ‚Π΅ΡΡŒ Π΄ΠΎΡ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ внСшниС Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΏΠΎΠ΄ свои Π½ΡƒΠΆΠ΄Ρ‹ – ΠΈΠ½ΠΎΠ³Π΄Π° этом ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ эффСктивнСС ΠΈ Π΄Π°ΠΆΠ΅ ΠΏΡ€ΠΎΡ‰Π΅, Ρ‡Π΅ΠΌ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ вашСго собствСнного ΠΊΠΎΠ΄Π°.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ