Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Калі-небудзь у далёкай будучыні аўтаматычнае выдаленне непатрэбных дадзеных будзе адной з важных задач СКБД [1]. Пакуль жа нам самім трэба клапаціцца аб выдаленні ці перасоўванні непатрэбных дадзеных на меней дарагія сістэмы захоўвання. Дапушчальны, вы вырашылі выдаліць некалькі мільёнаў радкоў. Даволі простая задача, асабліва калі вядома ўмова і ёсць прыдатны індэкс. "DELETE FROM table1 WHERE col1 = :value" - што можа быць прасцей, так?

Відэа:

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

  • Я ў праграмным камітэце Highload з першага года, т. е. з 2007-га.

  • І з Postgres я з 2005-га года. Выкарыстоўваў яго ў многіх праектах.

  • Гурт з RuPostges таксама з 2007-га года.

  • Мы на Meetup дараслі да 2100+ удзельнікаў. Гэта другое месца ў свеце пасля Нью-Ёрка, абагналі Сан-Францыска ўжо даўно.

  • Некалькі гадоў я жыву ў Каліфорніі. Займаюся больш амерыканскімі кампаніямі, у тым ліку буйнымі. Яны актыўныя карыстачы Postgres. І там узнікаюць усякія цікавыя штукі.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

https://postgres.ai/ - Гэта мая кампанія. Мы займаемся тым, што аўтаматызуем задачы, якія ўхіляюць запаволенне распрацоўкі.

Калі вы нешта робіце, то часам вакол Postgres узнікаюць нейкія затыкі. Дапушчальны, вам трэба пачакаць, пакуль адмін падніме вам тэставы стэнд, альбо вам трэба пачакаць, пакуль DBA на вас адрэагуе. І мы знаходзім такія вузкія месцы ў працэсе распрацоўкі, тэсціравання і адміністравання і стараемся іх ліквідаваць з дапамогай аўтаматызацыі і новых падыходаў.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

https://www.seagate.com/files/www-content/our-story/trends/files/idc-seagate-dataage-whitepaper.pdf

Я быў нядаўна на VLDB у Лос-Анджэлесе. Гэта самая вялікая канферэнцыя па базах даных. І там быў даклад аб тым, што ў будучыні СКБД будуць не толькі захоўваць, а яшчэ і аўтаматычна выдаляць дадзеныя. Гэта новая тэма.

Дадзеных усё больш у свеце зетабайт - гэта 1 000 000 петабайт. І зараз ужо ацэньваецца, што ў нас больш за 100 зэтабайт дадзеных у свеце захоўваецца. І іх робіцца ўсё больш і больш.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

https://vldb2019.github.io/files/VLDB19-keynote-2-slides.pdf

І што з гэтым рабіць? Зразумела, што трэба выдаляць. Вось спасылка на гэты цікавы даклад. Але пакуль што ў СКБД гэта не рэалізавана.

Тыя, хто ўмеюць лічыць грошы, жадаюць двух рэчаў. Яны жадаюць, каб мы выдалялі, таму тэхнічна мы павінны ўмець гэта рабіць.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Тое, што далей я буду расказваць, гэта некаторая абстрактная сітуацыя, якая ўключае ў сябе кучу рэальных сітуацый, г. зн. нейкая кампеляцыя таго, што адбывалася насамрэч са мной і навакольнымі базамі даных шмат разоў, шмат гадоў. Граблі ўсюды і на іх увесь час усё надыходзяць.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Дапусцім у нас ёсць база або некалькі баз, якія растуць. І некаторыя запісы – гэта відавочнае смецце. Напрыклад, карыстач нешта там пачаў рабіць, не скончыў. І праз нейкі час мы ведаем, што гэтае няскончанае можна ўжо не захоўваць. Т. е. нейкія смеццевыя рэчы мы хацелі б пачысціць, каб зэканоміць месца, палепшыць прадукцыйнасць і г. д.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Увогуле, ставіцца задача аўтаматызаваць выдаленне пэўных рэчаў, канкрэтных радкоў у нейкай табліцы.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

І ў нас ёсць такі запыт, пра які мы будзем сёння казаць, т. е. пра выдаленне смецця.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Папрасілі дасведчанага распрацоўніка гэта зрабіць. Ён узяў гэты запыт, праверыў у сябе - усё працуе. Пратэставаў на staging - усё добра. Выкацілі - усё працуе. Раз у суткі мы запускаем гэта - усё добра.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

БД расце і расце. Штосутачны DELETE крыху павольней працаваць пачынае.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Потым мы разумеем, што ў нас зараз маркетынгавая кампанія і трафік будзе ў некалькі разоў большы, таму вырашаем лішнія рэчы часова на паўзу паставіць. І забываем вярнуць.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Праз некалькі месяцаў прыгадалі. А той распрацоўшчык звольніўся або заняты нечым іншым, даручылі іншаму вярнуць.

Ён праверыў на dev, на staging - усё Ок. Натуральна, трэба яшчэ пачысціць тое, што назапасілася. Ён праверыў, усё працуе.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Што адбываецца далей? Далей у нас усё губляецца. Раняецца так, што ў нас у нейкі момант усё кладзецца. Усё ў шоку, ніхто не разумее, што адбываецца. І потым высвятляецца, што справа ў гэтым была DELETE.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Што пайшло не так? Вось тут дадзены спіс таго, што магло пайсці не так. Што з гэтага найважнейшае?

  • Напрыклад, не было review, т. е. DBA-эксперт не паглядзеў. Ён бы дасведчаным поглядам адразу знайшоў бы праблему, да таго ж у яго ёсць доступ да prod, дзе назапасілася некалькі мільёнаў радкоў.

  • Можа, правяралі неяк не так.

  • Можа быць жалеза састарэла і трэба апгрэйд для гэтай базы рабіць.

  • Ці нешта з самай базай дадзеных не так, і нам з Postgres на MySQL трэба пераехаць.

  • Ці, можа, з аперацыяй нешта не так.

  • Можа, якія памылкі ў арганізацыі працы і трэба кагосьці звольніць, а наняць лепшых людзей?

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Не было праверкі DBA. Калі DBA быў бы, ён убачыў бы гэтыя некалькі мільёнаў радкоў і нават без усялякіх эксперыментаў сказаў бы: "Так не робяць". Дапушчальны, калі б гэты код быў у GitLab, GitHub і быў бы працэс code review і не было такога, што без зацвярджэння DBA гэтая аперацыя пройдзе на prod, то відавочна DBA сказаў бы: "Так нельга рабіць".

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

І ён бы сказаў, што ў вас з disk IO будуць праблемы і ўсе працэсы ашалеюць, могуць быць Локі, а таксама вы заблакуеце аўтавакуум на кучу хвілін, таму гэта не добра.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

http://bit.ly/nancy-hl2018-2

Другая памылка - правяралі не там. Мы постфактум убачылі, што смеццевых дадзеных назапасілася на prod шмат, а ў распрацоўніка не было ў гэтай базе назапашаных дадзеных, ды і на staging асоба ніхто гэтае смецце не ствараў. Адпаведна, там было 1 радкоў, якія хутка адпрацавалі.

Мы разумеем, што нашы тэсты слабыя, т. е. працэс, які выбудаваны, не ловіць праблемы. Не праводзілі адэкватны БД-эксперымент.

Ідэальны эксперымент пажадана праводзіць на такім жа абсталяванні. На такім жа абсталяванні не заўсёды атрымоўваецца гэта зрабіць, але вельмі важна, каб гэта была поўнапамерная копія базы дадзеных. Гэта тое, што я прапаведаю ўжо некалькі гадоў. І год таму я пра гэта казаў, можаце ў YouTube гэта ўсё паглядзець.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Можа быць, у нас абсталяванне дрэннае? Калі паглядзець, то latency падскочыла. Мы ўбачылі, што утылізацыя 100%. Вядома, калі гэта былі б сучасныя NVMe дыскі, то, мусіць, нам было бы нашмат лягчэй. І, магчыма, мы б не ляглі ад гэтага.

Калі ў вас аблокі, то там апгрэйд лёгка робіцца. Узнялі новыя рэплікі на новым жалезе. Switchover. І ўсё добра. Даволі лёгка.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

А ці можна неяк паменш дыскі чапаць? І тут якраз з дапамогай DBA мы ныраем у некаторую тэму, якая называецца checkpoint tuning. Высьвятляецца, што ў нас ня быў праведзены checkpoint tuning.

Што такое checkpoint? Гэта ёсць у любой СКБД. Калі ў вас дадзеныя ў памяці мяняюцца, яны не адразу запісваюцца на дыскі. Інфармацыя аб тым, што дадзеныя змяніліся, спачатку запісваецца ў апераджальны часопіс, у write-ahead log. І ў нейкі момант СКБД вырашае, што час ужо рэальныя старонкі на дыск скінуць, каб, калі ў нас будзе збой, паменш рабіць REDO. Гэта як у цаццы. Калі нас заб'юць, мы будзем пачынаць гульню з апошняга checkpoint. І ўсе СКБД гэта рэалізуюць.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Налады ў Postgres адстаюць. Яны разлічана на 10-15-гадовай даўніны аб'ёмы даных і аперацый. І checkpoint - не выключэнне.

Вось гэтая інфармацыя з нашай справаздачы з Postgres check-up, г. зн. аўтаматычная праверка здароўя. І вось нейкая база ў некалькі тэрабайт. І бачна добра, што прымусовыя checkpoints амаль у 90% выпадкаў.

Гэта што значыць? Там ёсць дзве наладкі. Checkpoint можа па timeout наступіць, напрыклад, у 10 хвілін. Ці ён можа наступіць, калі напоўнілася даволі шмат звестак.

І па змаўчанні max_wal_saze выстаўлены ў 1 гігабайт. Па факце, гэта рэальна здараецца ў Postgres праз 300-400 мегабайт. Вы памянялі столькі дадзеных і ў вас checkpoint здараецца.

І калі гэта ніхто не цюніў, а сэрвіс вырас, і кампанія зарабляе кучу грошай, у яе шмат транзакцый, то checkpoint надыходзіць раз у хвіліну, часам і раз у 30 секунд, а часам нават і накладваюцца сябар на сябра. Гэта зусім ужо дрэнна.

І нам трэба зрабіць так, каб ён надыходзіў радзей. Т. е. мы можам падняць max_wal_size. І ён будзе надыходзіць радзей.

Але мы распрацавалі ў сябе цэлую метадалогію, як гэта зрабіць больш правільна, т. е. як прымаць рашэнне аб выбары налад, выразна абапіраючыся на пэўныя дадзеныя.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Адпаведна, мы робім дзве серыі эксперыментаў над базамі даных.

Першая серыя - мы мяняем max_wal_size. І праводзім масавую аперацыю. Спачатку які робіцца яе на дэфолтнай наладзе ў 1 гігабайт. І робім масавы DELETE многіх мільёнаў радкоў.

Відаць, як нам цяжка. Глядзім, што disk IO вельмі дрэнны. Глядзім, колькі WAL мы згенеравалі, бо гэта вельмі важна. Глядзім, колькі разоў checkpoint здарыўся. І бачым, што нядобра.

Далей мы павялічваем max_wal_size. Паўтараем. Павялічваем, паўтараем. І так шмат разоў. У прынцыпе, 10 кропак - гэта добра, дзе 1, 2, 4, 8 гігабайт. І глядзім паводзіны канкрэтнай сістэмы. Зразумела, што тут абсталяваньне павінна быць як на prod. У вас павінны быць тыя ж дыскі, колькі ж памяці і налады Postgres такія ж.

І такім чынам мы абмяняем нашу сістэму, і ведаем, як будзе сябе паводзіць СКБД пры дрэнным масавым DELETE, як будзе яна checkpoint'іцца.

Checkpoint па-руску - гэта кантрольныя кропкі.

Прыклад: DELETE некалькі млн радкоў па індэксе, радкі "раскіданыя" па старонках.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Вось прыклад. Гэта некаторая база. І пры дэфолтнай наладзе ў 1 гігабайт для max_wal_size вельмі добра відаць, што ў нас дыскі на запіс ідуць у паліцу. Вось такая карцінка - гэта тыповы сімптом вельмі хворага пацыента, т. е. яму рэальна было дрэнна. І тут была адна адзіная аперацыя, тут быў як раз DELETE некалькіх мільёнаў радкоў.

Калі такую ​​аперацыю пускаць у prod, то якраз мы і ляжам, таму што бачна, што адзін DELETE забівае нас у палку.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Далей, дзе 16 гігабайт, бачна, што ўжо зубчыкі пайшлі. Зубчыкі - гэта ўжо лепш, т. е. мы стукаемся аб столь, але ўжо не так дрэнна. Невялікая свабода там зьявілася. Справа - гэта запіс. І колькасць аперацый - другі графік. І відаць, што мы ўжо крыху лягчэй задыхалі, калі 16 гігабайт.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

А дзе 64 гігабайт бачна, што зусім лепш стала. Ужо зубчыкі ярка выяўленыя, з'яўляецца больш магчымасцей, каб выжыць іншым аперацыям і нешта зрабіць з дыскам.

Чаму так?

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Я буду крыху акунацца ў падрабязнасці, але гэтая тэма, як праводзіць checkpoint tuning, можа выліцца ў цэлы даклад, таму я не буду моцна грузіць, але крыху пазначу, якія там складанасці ёсць.

Калі checkpoint занадта часта здараецца, і мы абнаўляем нашы радкі не паслядоўна, а знаходзім па азначніку, што добра, таму што мы не ўсю табліцу выдаляе, тое можа здарыцца так, што спачатку мы першую старонку пакраталі, потым тысячную, а потым вярнуліся да першай . І калі паміж гэтымі заходамі ў першую старонку checkpoint яе ўжо на дыск захаваў, то ён яшчэ раз будзе яе захоўваць, таму што мы яе другі раз папэцкалі.

І мы будзем прымушаць checkpoint яе шмат разоў захоўваць. Як бы ўзнікаюць залішнія аперацыі для яго.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Але гэта яшчэ ня ўсё. У Postgres старонкі важаць 8 кілабайт, а ў Linux 4 кілабайт. І ёсць настройка full_page_writes. Па змаўчанні яна ўключана. І гэта правільна, таму што, калі мы яе выключым, то ёсць небяспека, што пры збоі толькі палоўка старонкі захаваецца.

Паводзіны запісу ў WAL апераджальнага часопіса такія, што, калі ў нас checkpoint здарыўся і мы старонку ў першы раз мяняем, то ў апераджальны часопіс трапляе ўся старонка цалкам, т. е. усе 8 кілабайт, хоць мы мянялі толькі радок, якая важыць 100 байт . І мы вымушаны цалкам старонку запісаць.

У наступных зменах будуць ужо толькі пэўны картэж, але ўпершыню ўсю запісваем.

І, адпаведна, калі checkpoint яшчэ раз здарыўся, то мы павінны зноў з нуля ўсё пачынаць і ўсю старонку запіхваць. Пры частых checkpoints, калі мы гуляем па адных і тых жа старонках, full_page_writes = on будзе больш, чым магло б быць, т. е. мы больш WAL генеруемы. Больш адпраўляецца на рэплікі, у архіў, на кружэлку.

І, адпаведна, дзве надмернасці ў нас узнікаюць.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Калі мы павялічваем max_wal_size, атрымліваецца, што мы палягчаем працу і checkpoint, і wal writer. І гэта класна.

Давайце паставім тэрабайт і будзем з гэтым жыць. Што ў гэтым дрэннага? Гэта дрэнна, таму што ў выпадку збою мы будзем паднімацца гадзінамі, таму што checkpoint быў даўно і ўжо шмат што змянілася. І нам на ўсё гэтае REDO трэба зрабіць. І таму мы робім другую серыю эксперыментаў.

Мы робім аперацыю і глядзім, калі checkpoint блізкі да таго, каб завершыцца, мы робім kill -9 Postgres спецыяльна.

І пасля гэтага стартуем яго нанова, і глядзім, як доўга ён будзе паднімацца на гэтым абсталяванні, т. е. колькі ён будзе рабіць REDO у гэтай дрэннай сітуацыі.

Двойчы адзначу, што сытуацыя дрэнная. Па-першае, мы ўпалі прама перад завяршэннем checkpoint, адпаведна, нам прайграваць шмат трэба. І, па-другое, у нас была масіўная аперацыя. І калі б checkpoints былі па тайм-аўце, то, хутчэй за ўсё, менш WAL згенеравалася б з моманту апошняга checkpoint. Г. зн. гэта двойчы няўдачнік.

Мы замяраем такую ​​сітуацыю для рознага памеру max_wal_size і разумеем, што, калі max_wal_size 64 гігабайта, то ў падвойнай горшай сітуацыі мы будзем паднімацца 10 хвілін. І думаем - задавальняе нас гэта ці не. Гэта бізнес-пытанне. Мы павінны паказаць гэтую карціну тым, хто адказвае за бізнэс-рашэнні і спытаць: «Колькі мы можам праляжаць максімум у выпадку праблемы? Ці можам мы паляжаць у горшай сітуацыі 3-5 хвілін?». І прымаеце рашэнне.

І тут ёсць цікавы момант. У нас на канферэнцыі ёсць пара дакладаў пра Patroni. І, магчыма, вы яго карыстаецеся. Гэта autofailover для Postgres. GitLab і Data Egret пра гэта расказвалі.

І калі ў вас есць autofailover, які наступіць праз 30 секунд, то можа быць мы і 10 хвілін можам праляжаць? Бо мы да гэтага моманту пераключымся на рэпліку, і ўсё будзе добра. Гэта пытанне спрэчнае. Я не ведаю дакладнага адказу. Я толькі адчуваю, што не толькі вакол узнаўлення пасля збою гэтая тэма.

Калі ў нас доўгае аднаўленне пасля збою, то нам будзе няёмка ў шматлікіх іншых сітуацыях. Напрыклад, у тых жа эксперыментах, калі мы нешта робім і вымушаны часам чакаць па 10 хвілін.

Я б усё ж не хадзіў занадта далёка, нават калі ў нас ёсць autofailover. Як правіла, такія значэнні, як 64, 100 гігабайт - гэта добрыя значэнні. Часам нават варта менш абраць. Увогуле, гэта тонкая навука.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Вам, каб ітэрацыі рабіць, напрыклад, max_wal_size =1, трэба паўтараць масавую аперацыю шмат разоў. Вы яе зрабілі. І на той жа базе хочаце яе яшчэ раз зрабіць, але вы ж ужо ўсё выдалілі. Што рабіць?

Я пазней раскажу пра нашае рашэнне, што мы робім для таго, каб ітэраваць у такіх сітуацыях. І гэта самы слушны падыход.

Але ў дадзеным выпадку нам павезла. Калі, як тут напісана "BEGIN, DELETE, ROLLBACK", то мы можам DELETE паўтараць. Т. е. калі мы яго адмянілі самі, то мы можам яго паўтараць. І фізічна ў вас дадзеныя будуць тамака жа ляжаць. У вас нават bloat ніякага не ўтворыцца. Вы можаце ітэраваць на такіх DELETE.

Такі DELETE c ROLLBACK ідэальны для checkpoint tuning, нават калі ў вас няма нармальна разгорнутай database labs.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Мы зрабілі таблічку з адной калонкай "i". У Postgres ёсць службовыя калонкі. Яны нябачныя, калі іх спецыяльна не папрасіць. Гэта: ctid, xmid, xmax.

Ctid - гэта фізічны адрас. Нулявая старонка, першы картэж у старонцы.

Відаць, што пасля ROOLBACK картэж застаўся на тым самым месцы. Т. е. мы можам яшчэ раз паспрабаваць, яно будзе сябе паводзіць гэтак жа. Гэта галоўнае.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Xmax - гэта час смерці картэжа. Ён праставіўся, але Postgres ведае, што гэтая транзакцыя была адкачаная, таму, што 0, што адкачаная транзакцыя – усё роўна. Гэта сведчыць аб тым, што па DELETE можна ітэраваць і правяраць масавыя аперацыі паводзін сістэмы. Можна зрабіць database labs для бедных.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Гэта ўжо пра праграмістаў. Пра DBA таксама, яны заўсёды за гэта праграмістаў лаюць: "Навошта вы робіце такія доўгія і цяжкія аперацыі?". Гэта зусім іншая перпендыкулярная тэма. Раней было адміністраванне, а зараз будзе распрацоўка.

Відавочна, што мы не разбілі на часткі. Гэта зразумела. Нельга такі DELETE для кучы мільёнаў радкоў не разбіваць на часткі. Ён будзе рабіцца 20 хвілін, і ўсё будзе ляжаць. Але, нажаль, памылкі здзяйсняюць нават дасведчаныя распрацоўнікі, нават у вельмі буйных кампаніях.

Чаму важна разбіваць?

  • Калі мы бачым, што дыску цяжка, то давайце замарудзім. І калі ў нас разбіта, то мы можам паўзы дадаць, можам запаволіць throttling.

  • І мы іншых не будзем блакіраваць надоўга. У некаторых выпадках гэта ўсё роўна, калі вы выдаляеце рэальнае смецце, з якім ніхто не працуе, то, хутчэй за ўсё, вы нікога не заблакуеце, акрамя працы autovacuum, таму што ён будзе чакаць, калі транзакцыя завершыцца. Але калі вы выдаляеце тое, што нехта можа яшчэ запытаць, то яны будуць блакавацца, пойдзе нейкая ланцуговая рэакцыя. На сайтах і ў мабільных дадатках трэба пазбягаць доўгіх транзакцый.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

https://postgres.ai/products/joe/

Гэта цікава. Я часта сустракаю, што распрацоўшчыкі пытаюцца: "Які памер пачкі абраць?".

Зразумела, чым большы памер пачка, тым менш transaction overhead, т. е. дадатковыя накладныя выдаткі ад транзакцый. Але пры гэтым час павялічваецца ў гэтай транзакцыі.

У мяне ёсць вельмі простае правіла: вазьміце як мага больш, але не перавышайце выкананні ў секунду.

Чаму секунду? Тлумачэнне вельмі простае і зразумелае ўсім, нават не тэхнічным людзям. Мы бачым рэакцыю. Возьмем 50 мілісекунд. Калі нешта змянілася, то вока наша зрэагуе. Калі менш, дык складаней. Калі нешта адказвае праз 100 мілісекунд, напрыклад, вы мышкай націснулі, і яно вам праз 100 мілісекунд адказала, вы ўжо адчуваеце гэтую невялікую затрымку. Секунда ўжо ўспрымаецца як тормазы.

Адпаведна, калі мы нашыя масавыя аперацыі разаб'ём на 10-ці секундныя пачкі, то ў нас ёсць рызыка, што мы кагосьці заблакім. І ён будзе працаваць некалькі секунд, і гэта людзі ўжо заўважаць. Таму я аддаю перавагу больш за секунду не рабіць. Але ў той жа час і зусім дробна не разбіваць, таму што transaction overhead будзе замецены. Базе будзе цяжэй, могуць узнікнуць яшчэ іншыя розныя праблемы.

Мы падбіраем памер пачка. У кожным выпадку можам гэта рабіць па-рознаму. Можна аўтаматызаваць. І пераконваемся ў эфектыўнасці працы апрацоўкі аднаго пачка. Т. е. мы робім DELETE адной пачкі або UPDATE.

Дарэчы, усё, што я расказваю, гэта не толькі пра DELETE. Як вы здагадаліся, гэта любыя масавыя аперацыі над дадзенымі.

І мы глядзім, што план выдатны. Відаць index scan, яшчэ лепш index only scan. І ў нас невялікая колькасць дадзеных задзейнічана. І ўсё менш секунды адпрацоўвае. Супер.

І мы яшчэ павінны ўпэўніцца, што дэградацыі няма. Бывае, што першыя пачкі хутка адпрацоўваюць, а потым усё горш-горш і горш. Працэс такі, што трэба шмат тэсціраваць. Для гэтага якраз і патрэбная database labs.

І мы яшчэ павінны падрыхтаваць нешта, каб гэта нам дазволіла ў production за гэтым правільна сачыць. Напрыклад, мы можам у логу пісаць час, можам пісаць, дзе мы зараз і каго мы зараз выдалілі. І гэта нам дазволіць потым разумець, што адбываецца. І ў выпадку, калі нешта пойдзе не так, хутка знайсці гэтую праблему.

Калі нам трэба праверыць эфектыўнасць запытаў і нам трэба ітэраваць шмат разоў, то як раз ёсць такая штука, як таварыш бот. Ён ужо готаў. Ён выкарыстоўваецца дзясяткамі распрацоўшчыкамі штодня. І ён умее велізарную тэрабайтную базу даць па запыце за 30 секунд, вашу ўласную копію. І вы можаце нешта там выдаліць і сказаць RESET, і яшчэ раз выдаліць. Вы можаце з ім эксперыментаваць такім чынам. Я бачу за гэтай штукай будучыню. І мы гэта ўжо робім.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

https://docs.gitlab.com/ee/development/background_migrations.html

Якія ёсць стратэгіі разбіцця? Я бачу 3 розныя стратэгіі разбіцця, якія выкарыстоўваюць распрацоўшчыкі на пачку.

Першая вельмі простая. У нас ёсць айдышнік лікавы. І давайце мы разаб'ем на розныя інтэрвалы, і будзем працаваць з гэтым. Мінус зразумелы. У першым адрэзку ў нас рэальнага смецця можа патрапіць 100 радкоў, у другім 5 радкоў ці ўвогуле не патрапіць, ці ўсе 1 000 радкоў апынуцца смеццем. Вельмі нераўнамерная праца, але затое разбіваць лёгка. Узялі максімальны ID і разбілі. Гэта наіўны падыход.

Другая стратэгія - гэта збалансаваны падыход. Ён выкарыстоўваецца ў Gitlab. Узялі і прасканавалі табліцу. Выявілі межы пачкаў ID так, каб кожны пачак быў роўна па 10 000 запісаў. І засунулі ў нейкую чаргу. І далей апрацоўваем. Можна гэта рабіць у некалькі плыняў.

У першай стратэгіі таксама, дарэчы, можна гэта рабіць у некалькі плыняў. Гэта не складана.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

https://medium.com/@samokhvalov/how-partial-indexes-affect-update-performance-in-postgres-d05e0052abc

Але ёсць больш класны і аптымальны падыход. Гэта трэцяя стратэгія. І калі гэта магчыма, то лепей яе выбіраць. Мы на аснове спецыяльнага індэкса гэта робім. У дадзеным выпадку гэта будзе, хутчэй за ўсё, азначнік па нашай умове смецця і ID. Мы ўключым ID, каб гэта быў index only scan, каб мы ў heap не хадзілі.

Як правіла, index only scan - гэта хутчэй, чым index scan.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

І мы хутка знаходзім нашы айдышнікі, якія мы хочам выдаліць. BATCH_SIZE мы падбіраем загадзя. І мы іх не толькі атрымліваем, мы іх атрымліваем спецыяльным чынам і тут жа лочым. Але так лачым, што, калі яны ўжо залочаны, мы іх не лачым, а едзем далей і бярэм наступныя. Гэта для update skip locked. Гэтая суперфіч Postgres нам дазваляе ў некалькі патокаў працаваць, калі мы хочам. Можна ў адну плынь. І тут ёсць CTE - гэта адзін запыт. І ў нас у другім паверсе гэтага CTE адбываецца рэальнае выдаленне - returning *. Можна returning id, але лепш *, Калі ў вас дадзеных трохі ў кожным радку.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Навошта нам гэта патрэбна? Гэтым нам трэба для таго, каб даць справаздачу. Мы зараз выдалілі гэтулькі радкоў па факце. І ў нас межы па ID ці па created_at вось вось такія. Можна min, max зрабіць. Яшчэ нешта можна зрабіць. Тут можна шматлікае запіхаць. І гэта для маніторынгу вельмі зручна.

Наконт індэкса ёсць яшчэ адна заўвага. Калі мы вырашылі, што нам менавіта для гэтай задачы патрэбен адмысловы азначнік, то трэба пераканацца, што ён не сапсуе heap only tuples updates. Т. е. у Postgres ёсць такая статыстыка. Гэта можна паглядзець у pg_stat_user_tables для вашай табліцы. Вы можаце паглядзець - ці выкарыстоўваецца hot updates ці не.

Бываюць сітуацыі, калі ваш новы азначнік можа іх проста абсекчы. І ў вас усе іншыя updates, якія ўжо працуюць, замарудзяцца. Не проста таму што азначнік з'явіўся (кожны азначнік ледзь запавольвае updates, але ледзь-ледзь), а тут ён яшчэ сапсуе. І адмысловую аптымізацыю зрабіць для гэтай табліцы немагчыма. Такое часам бывае. Гэта такая тонкасць, пра якую мала хто памятае. І на гэтыя граблі лёгка наступіць. Часам бывае, што трэба падыход з іншага боку знайсці і ўсёткі абыйсціся без гэтага новага азначніка, або зрабіць іншы азначнік, або яшчэ як-небудзь, напрыклад, можна выкарыстаць другі метад.

Але гэта самая аптымальная стратэгія, як разбіваць на batches і адным запытам страляць па пачках, выдаляць па ледзь-ледзь і т. д.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Доўгія транзакцыі https://gitlab.com/snippets/1890447

Blocked autovacuum https://gitlab.com/snippets/1889668

Blocking issue - https://gitlab.com/snippets/1890428

Памылка №5 вялікая. Мікалай з Okmeter расказваў пра маніторынг Postgres. Ідэальнага маніторынгу Postgres, нажаль, не існуе. Нехта бліжэй, нехта далей. Okmeter - досыць блізкі да таго, каб быць ідэальным, але шмат чаго не хапае і трэба дадаваць. Да гэтага трэба быць падрыхтаваным.

Напрыклад, dead tuples лепш маніторыць. Калі ў вас шмат мерцвячыны ў табліцы, то тут нешта не так. Лепш рэагаваць зараз, а то там можа быць дэградацыя, і мы можам легчы. Такое бывае.

Калі вялікае IO, то зразумела, што гэта нядобра.

Доўгія транзакцыі таксама. На OLTP доўгія транзакцыі не варта пускаць. І вось тут спасылка на сніпет, якая дазваляе ўзяць гэты сніпет і ўжо зрабіць некаторае сачэнне за доўгімі транзакцыямі.

Чаму доўгія транзакцыі - гэта дрэнна? Бо ўсе локі адпусцяцца толькі ў канцы. І мы лацім усіх. Плюс мы блакуем працу autovacuum для ўсіх табліц. Гэта ўвогуле не добра. Нават калі на рэпліцы ў вас hot standby уключаны, гэта ўсё роўна дрэнна. Увогуле, нідзе лепш не дапушчаць доўгіх транзакцый.

Калі ў нас шмат табліц не вакумуюцца, то трэба alert мець. Тут магчыма такая сітуацыя якраз. Мы ўскосна можа паўплываць на працу autovacuum. Гэта сниппет ад Avito, які я крыху палепшыў. І атрымаўся цікавы інструмент, каб паглядзець, што ў нас з autovacuum. Напрыклад, там чакаюць нейкія табліцы і не дачакаюцца сваёй чаргі. Таксама трэба засунуць у маніторынг і мець alert.

І блокі issues. Лес дрэў блакіровак. Я кахаю ў кагосьці нешта ўзяць і палепшыць. Тут ад Data Egret узяў класны рэкурсіўны CTE, які паказвае лес дрэў блакіровак. Гэта добрая штука для дыягностыкі. І на яе аснове таксама можна збудаваць маніторынг. Але ж гэта трэба акуратна рабіць. Трэба самому сабе statement_timeout маленькі зрабіць. І lock_timeout пажадана.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Часам усе гэтыя памылкі сустракаюцца ў суме.

На мой погляд, самая галоўная памылка тут - гэта арганізацыйная. Яна арганізацыйная, бо тэхніка не цягне. Гэта нумар 2 - правяралі не там.

Мы правяралі ня там, таму што ў нас не было клона production, на якім лёгка праверыць. У распрацоўніка наогул можа не быць доступу да production.

І мы правяралі не там. Калі б правяралі там, там мы самі б гэта ўбачылі. Распрацоўнік і без DBA гэта ўсё ўбачыў, калі ён правяраў гэта ў добрым асяроддзі, дзе дадзеных столькі ж і ідэнтычнае размяшчэнне. Ён бы ўсю гэтую дэградацыю ўбачыў бы і яму сорамна было б.

Яшчэ пра аўтавакуум. Пасля таго, як мы зрабілі масіўную зачыстку некалькіх мільёнаў радкоў, яшчэ трэба REPACK зрабіць. Асабліва для азначнікаў гэта важна. Ім будзе дрэнна пасля таго, як мы тамака ўсё пачысцілі.

І калі вы хочаце вярнуць штодзённую працу па зачыстцы, то я б прапанаваў гэта рабіць часцей, але драбней. Можна раз у хвілін ці яшчэ часцей пакрысе. І трэба наладзіць маніторынг дзвюх рэчаў: што памылак няма ў гэтай штучкі і што яна не адстае. Той трук, які я паказваў якраз дазволіць гэтае вырашыць.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Тое, што мы робім, гэта open source. Гэта выкладзена на GitLab. І мы робім так, каб людзі маглі правяраць нават без DBA. Мы робім database lab, г. зн. мы так называем базавы кампанент, на якім зараз працуе Joe. І вы можаце ўзяць копію production. Цяпер ёсць рэалізацыя Joe для slack, вы можаце там сказаць: "explain вось такі запыт" і тут жа атрымаць вынік для вашай копіі базы. Вы можаце там нават DELETE зрабіць, і ніхто гэтага не заўважыць.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Дапусцім, у вас 10 тэрабайта, мы робім database lab таксама 10 тэрабайт. І з адначасовымі 10-ці тэрабайтнымі базамі могуць працаваць адначасова 10 распрацоўшчыкаў. Кожны можа рабіць тое, што жадае. Можа выдаляць, драпаць і г. д. Вось такая фантастыка. Пра гэта мы заўтра будзем казаць.

Дарагі DELETE. Мікалай Самахвалаў (Postgres.ai)

Гэта называецца thin provisioning. Гэта тонкі провіжынг. Гэта такая некаторая фантастыка, якая моцна прыбірае затрымкі ў распрацоўцы, у тэсціраванні і робіць свет лепшым у гэтым плане. Т. е. як раз дазваляе вам пазбягаць праблем з масавымі аперацыямі.

Прыклад: база дадзеных у 5 тэрабайт, атрыманне копіі менш, чым за 30 секунд. І ад памеру гэта нават не залежыць, т. е. усё роўна, колькі тэрабайт.

Ужо сёння вы можаце зайсці на Postgres.ai і пакапацца ў нашых інструментах. Вы можаце зарэгістравацца, паглядзець, што тамака ёсць. Можаце паставіць сабе гэтага робата. Ён бясплатны. Пішыце.

пытанні

Вельмі часта ў рэальных сітуацыях атрымліваецца так, што дадзеныя, якія павінны застацца ў табліцы, іх значна меншыя, чым трэба выдаліць. Т. е. у такой сітуацыі часта лягчэй ажыццявіць такі падыход, калі прасцей стварыць новы аб'ект, скапіяваць туды толькі патрэбныя дадзеныя і затранкейціть старую табліцу. Зразумела, што патрэбен праграмны падыход для гэтага моманту, пакуль у вас будзе адбывацца пераключэнне. Як такі падыход?

Гэта вельмі добры падыход і вельмі добрая задача. Яна вельмі падобная на тое, што робіць pg_repack, яна вельмі падобная на тое, што вам даводзіцца рабіць, калі вы айдышнікі зрабілі 4-х байтнымі. Многія фрэймворкі гэта рабілі некалькі гадоў таму, і якраз таблічкі падраслі, і іх трэба канвертаваць на 8 байт.

Гэта задача даволі цяжкая. Мы гэта рабілі. І вам трэба быць вельмі ахайнымі. Тамака локі і т. д. Але гэта робіцца. Т. е. стандартны падыход паход на pg_repack. Вы аб'яўляеце такую ​​таблічку. І перш чым у яе пачаць заліваць дадзеныя снапшотам, вы яшчэ аб'яўляеце адну таблічку, якая ўсе змены адсочвае. Там ёсць хітрасць, што некаторыя змены вы можаце нават не адсочваць. Ёсць тонкасці. І потым вы перамыкаецеся, накаціўшы змены. Там будзе нядоўгая паўза, калі мы ўсіх залачым, але ў цэлым гэта робіцца.

Калі вы pg_repack на GitHub паглядзіце, то там, калі была задача канвертаваць айдышнік з int 4 на int 8, то была ідэя сам pg_repack выкарыстоўваць. Гэта таксама магчыма, але гэта крыху хакерскі метад, але ён таксама для гэтага падыдзе. Вы можаце ўмяшацца ў трыгер, які выкарыстоўвае pg_repack і тамака сказаць: «Нам гэтыя дадзеныя не патрэбныя», т. е. мы пераліваем толькі тое, што нам трэба. І потым ён проста пераключыцца і ўсё.

Пры такім падыходзе мы яшчэ атрымліваем другую копію табліцы, у якой дадзеныя ўжо індэксаваць і выкладзены вельмі роўна з прыгожымі індэксамі.

Bloat не, гэта добры падыход. Але я ведаю, што ёсць спробы распрацаваць аўтаматызацыю для гэтага, т. е. зрабіць універсальнае рашэнне. Я магу звесці вас з гэтай аўтаматызацыяй. Яна напісана на Python, добрая штука.

Я проста трошкі са свету MySQL, таму я прыйшоў паслухаць. І мы карыстаемся такім падыходам.

Але ён толькі, калі ў нас 90%. Калі ў нас 5%, то не вельмі добра яго прымяняць.

Дзякуй за даклад! Калі няма рэсурсаў зрабіць поўную копію prod, ці ёсць нейкі алгарытм ці формула для таго, каб пралічыць нагрузку ці памер?

Добрае пытанне. Пакуль што ў нас атрымліваецца шматтэрабайтныя базы знайсці. Хай нават там жалеза не такое ж будзе, напрыклад, паменш памяці, паменш працэсара і дыскі не зусім такія ж, але ўсё ж мы робім гэта. Калі зусім няма дзе, дык трэба падумаць. Давайце я да заўтра падумаю, вы прыходзілі, мы пагутарым, гэта добрае пытанне.

Дзякуй за даклад! Вы спачатку пачалі пра тое, што ёсць круты Postgres, у якога вось вось такія абмежаванні, але ён развіваецца. А гэта ўсё мыліца па вялікім рахунку. Ці не ідзе гэта ўсё ў супярэчнасць з развіццём самога Postgres, у якім які-небудзь DELETE deferent з'явіцца ці што-небудзь яшчэ, што павінна падтрымліваць на нізкім узроўні тое, што мы спрабуем тут абшмараваць нейкімі сваімі дзіўнымі сродкамі?

Калі мы ў SQL сказалі выдаліць ці праапдэйціць шмат запісаў у адной транзакцыі, то як там Postgres можа гэта размеркаваць? Мы фізічна абмежаваны ў аперацыях. Мы ўсё роўна будзем гэта рабіць доўга. І мы будзем лачыць тым часам і т. д.

З індэксамі ж зрабілі.

Я магу меркаваць, што той жа checkpoint tuning можна было аўтаматызаваць. Некалі гэта, магчыма, будзе. Але я тады пытаньне ня надта разумею.

Пытанне ў тым, што ці няма такога вектара развіцця, які ідзе вось там вось, а тут ідзе паралельна ваша? Г.зн. там пакуль пра гэта не думаюць?

Я расказаў пра прынцыпы, якія можна выкарыстоўваць зараз. Ёсць іншы бот Нэнсі, з дапамогай гэтага можна зрабіць аўтаматызаваны checkpoint tuning. Ці будзе гэта некалі ў Postgres? Ня ведаю, гэта пакуль што нават не абмяркоўваецца. Мы пакуль далёкія ад гэтага. Але ёсць вучоныя, якія робяць новыя сістэмы. І яны нас піхаюць у аўтаматычныя індэксы. Ёсць распрацоўкі. Напрыклад, auto tuning можаце паглядзець. Ён падбірае параметры аўтаматычна. Але ен вам checkpoint tuning пакуль не зробіць. Т. е. ён падбярэ для performance, shell buffer і т. д.

А для checkpoint tuning можна зрабіць такую ​​штуку: калі ў вас тысяча кластараў і розныя жалязякі, розныя віртуальныя машыны ў cloud, вы можаце з дапамогай нашага робата Нэнсі аўтаматызацыю зрабіць. І будзе падбірацца max_wal_size па вашым мэтавым устаноўкам аўтаматычна. Але пакуль гэтага ў ядры нават блізка няма, нажаль.

Добры дзень! Вы казалі аб шкодзе доўгіх транзакцый. Вы казалі, што блакуюцца autovacuum у выпадку выдаленняў. Чым нам яшчэ гэта шкодзіць? Таму што мы больш гаворым аб вызваленні месца і магчымасці яго выкарыстоўваць. Што яшчэ мы губляем?

Autovacuum - гэта, можа быць, не самая вялікая праблема тут. А тое, што доўгая транзакцыя можа залачыць іншыя транзакцыі, гэтая магчымасць больш небяспечная. Яна можа сустрэцца, а можа і не спаткацца. Калі яна сустрэлася, дык вельмі дрэнна можа быць. І з autovacuum гэта таксама праблема. Тут дзве праблемы з доўгімі транзакцыямі ў OLTP: Локі і autovacuum. І калі ў вас hot standby feedback уключаны на рэпліцы, то вам яшчэ блакіроўка autovacuum прыляціць на майстар, яна прыляціць з рэплікі. Але, прынамсі, там локаў не будзе. А тут будуць локі. Мы гаворым аб зменах дадзеных, таму Локі - гэта важны тут момант. І калі гэта ўсё доўга-доўга, то ўсё больш транзакцый лачыцца. Яны могуць лачыць іншыя. І з'яўляюцца дрэвы локаў. Я прыводзіў спасылку на сниппет. І гэтая праблема хутчэй становіцца больш прыкметнымі, чым праблема з autovacuum, які можа толькі назапашвацца.

Дзякуй за даклад! Вы пачалі свой даклад з таго, што няправільна тэсціравалі. Працягнулі сваю ідэю, што трэба ўзяць абсталяванне аднолькавае, з базай сапраўды гэтак жа. Дапусцім, мы далі распрацоўніку базу. І ён выканаў запыт. І ў яго быццам бы ўсё добра. Але ж ён не правярае на live, а на live, напрыклад, у нас нагрузцы на 60-70 %. І нават калі мы выкарыстоўваем гэты цюнінг, атрымліваецца не вельмі.

Мець у камандзе эксперта і карыстацца экспертам DBA, якія могуць прагноз зрабіць, што будзе пры рэальнай фонавай нагрузцы, - гэта важна. Калі мы проста чыстыя нашы змены прагналі, мы бачым карціну. Але больш прасунуты падыход, калі мы яшчэ раз тое ж самае зрабілі, але яшчэ са сімуляванай з production нагрузкай. Гэта зусім класна. Да гэтага трэба яшчэ дарасці. Гэта па-даросламу. Мы і чыста паглядзелі, што ёсць і яшчэ паглядзелі - ці хапае нам рэсурсаў. Гэта добрае пытанне.

Калі мы ўжо які робіцца garbage select і ў нас ёсць, да прыкладу, deleted flag

Гэта тое, што autovacuum робіць аўтаматычна ў Postgres.

А, ён гэта робіць?

Autovacuum гэта і есць garbage collector.

Дзякуй!

Дзякуй за даклад! Ці ёсць варыянт адразу праектаваць базу дадзеных з партыцыраваннем такім, каб усё смецце адпачкоўвалася ад асноўнай табліцы куды-небудзь у бок?

Канешне ёсць.

Ці можна тады засцерагчы сябе, калі мы залачылі табліцу, якая не павінна выкарыстоўвацца?

Канешне ёсць. Але гэта пытанне як пра курыцу і яйка. Калі мы ўсё ведаем, што будзе ў будучыні, то, вядома, мы ўсё зробім класна. Але бізнес мяняецца, там з'яўляюцца новыя калонкі, новыя запыты. А потым - опа, мы жадаем гэта выдаліць. Але гэта ідэальная сітуацыя, у жыцці яна сустракаецца, але не заўсёды. Але ў цэлым гэта добрая ідэя. Проста truncate і ўсё.

Крыніца: habr.com

Дадаць каментар