Istorija apie fizinį 300 milijonų įrašų ištrynimą MySQL

įvedimas

Sveiki. Aš esu ningenMe, žiniatinklio kūrėjas.

Kaip sakoma pavadinime, mano istorija yra istorija apie fizinį 300 milijonų įrašų ištrynimą MySQL.

Susidomėjau tuo, todėl nusprendžiau padaryti priminimą (instrukcijas).

Pagrindinis puslapis – įspėjimas

Paketinis serveris, kurį naudoju ir prižiūriu, turi reguliarų procesą, kuris kartą per dieną renka paskutinio mėnesio duomenis iš MySQL.

Paprastai šis procesas baigiamas maždaug per 1 valandą, tačiau šį kartą jis nesibaigia 7 ar 8 valandas, o įspėjimas nesiliovė pasirodęs...

Priežasties radimas

Bandžiau iš naujo paleisti procesą ir pažvelgti į žurnalus, bet nemačiau nieko blogo.
Užklausa buvo tinkamai indeksuota. Bet kai pagalvojau, kas ne taip, supratau, kad duomenų bazės dydis yra gana didelis.

hoge_table | 350'000'000 |

350 milijonų įrašų. Atrodė, kad indeksavimas veikė tinkamai, tik labai lėtai.

Reikalingas duomenų rinkimas per mėnesį buvo maždaug 12 000 000 įrašų. Atrodo, kad pasirinkimo komanda užtruko ilgai, o operacija nebuvo vykdoma ilgą laiką.

DB

Iš esmės tai lentelė, kuri kasdien padaugėja maždaug 400 000 įrašų. Duomenų bazė turėjo kaupti tik paskutinio mėnesio duomenis, todėl buvo tikimasi, kad ji atlaikys būtent tokį duomenų kiekį, bet, deja, rotate operacija nebuvo įtraukta.

Šią duomenų bazę sukūriau ne aš. Aš jį perėmiau iš kito kūrėjo, todėl tai vis tiek atrodė kaip techninė skola.

Atėjo taškas, kai kasdien įterpiamas duomenų kiekis tapo didelis ir galiausiai pasiekė ribą. Spėjama, kad dirbant su tokiu dideliu duomenų kiekiu tektų juos atskirti, bet tai, deja, nebuvo padaryta.

Ir tada aš pradėjau veikti.

Pataisymas

Racionaliau buvo sumažinti pačios duomenų bazės dydį ir sutrumpinti jos apdorojimo laiką, nei keisti pačią logiką.

Situacija turėtų gerokai pasikeisti, jei ištrinsi 300 milijonų įrašų, todėl nusprendžiau taip... Ech, maniau, kad tai tikrai pasiseks.

1 veiksmas

Paruošęs patikimą atsarginę kopiją, pagaliau pradėjau siųsti užklausas.

''Prašymo siuntimas''

DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';

"…"

"…"

„Hm... Jokio atsakymo. Galbūt procesas užtrunka ilgai? — Pagalvojau, bet tik tuo atveju pažiūrėjau į grafaną ir pamačiau, kad disko apkrova labai greitai auga.
„Pavojinga“, – vėl pagalvojau ir iškart nutraukiau prašymą.

2 veiksmas

Viską išanalizavęs supratau, kad duomenų kiekis per didelis, kad būtų galima viską ištrinti iš karto.

Nusprendžiau parašyti scenarijų, kuris galėtų ištrinti apie 1 000 000 įrašų, ir paleidau jį.

„Aš įgyvendinu scenarijų“

„Dabar tai tikrai veiks“, – pagalvojau.

3 veiksmas

Antrasis metodas pasiteisino, bet pasirodė labai daug darbo reikalaujantis.
Viską atlikti kruopščiai, be nereikalingų nervų užtruktų apie dvi savaites. Bet vis tiek šis scenarijus neatitiko aptarnavimo reikalavimų, todėl teko nuo jo atsitraukti.

Taigi štai ką nusprendžiau padaryti:

Nukopijuokite lentelę ir pervardykite ją

Iš ankstesnio žingsnio supratau, kad ištrynus tokį didelį duomenų kiekį, susidaro vienodai didelė apkrova. Taigi nusprendžiau sukurti naują lentelę nuo nulio naudojant įterpimą ir perkelti duomenis, kuriuos ketinau ištrinti.

| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|

Jei naują lentelę padarysite tokio pat dydžio kaip aukščiau, duomenų apdorojimo greitis taip pat turėtų padidėti 1/7.

Sukūręs lentelę ir pervadinęs ją pradėjau naudoti kaip pagrindinę lentelę. Dabar, jei numesčiau lentelę su 300 milijonų įrašų, viskas turėtų būti gerai.
Sužinojau, kad sutrumpinimas arba nuleidimas sukuria mažiau papildomų išlaidų nei trynimas, ir nusprendžiau naudoti šį metodą.

Įvykdymas

''Prašymo siuntimas''

INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';

"…"
"…"
"Em...?"

4 veiksmas

Maniau, kad ankstesnė idėja pasiteisins, bet išsiuntus įterpimo užklausą atsirado kelios klaidos. MySQL neatleidžia.

Jau buvau toks pavargęs, kad pradėjau galvoti, kad daugiau to nebenoriu.

Sėdėjau, galvojau ir supratau, kad gal buvo per daug įterpimo užklausų vienam kartui...
Bandžiau išsiųsti įterpimo užklausą dėl duomenų kiekio, kurį duomenų bazė turėtų apdoroti per 1 dieną. Įvyko!

Na, o po to ir toliau siunčiame užklausas dėl tokio pat kiekio duomenų. Kadangi turime pašalinti mėnesio duomenis, šią operaciją kartojame maždaug 35 kartus.

Lentelės pervadinimas

Čia sėkmė buvo mano pusėje: viskas vyko sklandžiai.

Perspėjimas dingo

Padidėjęs paketinio apdorojimo greitis.

Anksčiau šis procesas užtrukdavo apie valandą, dabar – apie 2 minutes.

Įsitikinęs, kad visos problemos išspręstos, numečiau 300 milijonų rekordų. Ištryniau lentelę ir jaučiausi atgimęs.

Santrauka

Supratau, kad paketinio apdorojimo metu trūksta rotacinio apdorojimo, ir tai buvo pagrindinė problema. Tokia architektūrinė klaida leidžia gaišti laiką.

Ar ištrindami įrašus iš duomenų bazės galvojate apie apkrovą duomenų replikacijos metu? Neperkraukite MySQL.

Puikiai išmanantys duomenų bazes su tokia problema tikrai nesusidurs. Likusiems, tikiuosi, šis straipsnis buvo naudingas.

Ačiū, kad skaitėte!

Mums bus labai malonu, jei pasakysite, ar jums patiko šis straipsnis, ar vertimas aiškus, ar jis jums buvo naudingas?

Šaltinis: www.habr.com

Добавить комментарий