Kisah Penghapusan Fizikal 300 Juta Rekod dalam MySQL

Pengenalan

Hello. Saya ningenMe, pembangun web.

Seperti tajuknya, kisah saya ialah kisah memadam 300 juta rekod secara fizikal dalam MySQL.

Saya mula berminat dengan perkara ini, jadi saya memutuskan untuk membuat peringatan (arahan).

Rumah - Makluman

Pelayan kelompok yang saya gunakan dan selenggara mempunyai proses tetap yang mengumpul data bulan lepas daripada MySQL sekali sehari.

Biasanya proses ini selesai dalam masa kira-kira 1 jam, tetapi kali ini ia tidak selesai selama 7 atau 8 jam, dan amaran tidak berhenti muncul...

Mencari sebab

Saya cuba memulakan semula proses dan melihat log, tetapi saya tidak nampak apa-apa yang salah.
Pertanyaan telah diindeks dengan betul. Tetapi apabila saya berfikir tentang apa yang berlaku, saya menyedari bahawa saiz pangkalan data agak besar.

hoge_table | 350'000'000 |

350 juta rekod. Pengindeksan nampaknya berfungsi dengan betul, cuma sangat perlahan.

Pengumpulan data yang diperlukan sebulan adalah lebih kurang 12 rekod. Nampaknya arahan pilih mengambil masa yang lama dan transaksi tidak dilaksanakan untuk masa yang lama.

DB

Ia pada asasnya adalah jadual yang berkembang kira-kira 400 penyertaan setiap hari. Pangkalan data sepatutnya mengumpul data hanya untuk bulan lepas, oleh itu, ia dijangka akan menahan jumlah data ini, tetapi, malangnya, operasi putar tidak disertakan.

Pangkalan data ini tidak dibangunkan oleh saya. Saya mengambil alihnya daripada pemaju lain, jadi ia masih terasa seperti hutang teknikal.

Terdapat satu ketika apabila jumlah data yang dimasukkan setiap hari menjadi besar dan akhirnya mencapai hadnya. Diandaikan bahawa apabila bekerja dengan sejumlah besar data, adalah perlu untuk memisahkannya, tetapi ini, malangnya, tidak dilakukan.

Dan kemudian saya mula bertindak.

Pembetulan

Adalah lebih rasional untuk mengurangkan saiz pangkalan data itu sendiri dan mengurangkan masa untuk memprosesnya daripada mengubah logik itu sendiri.

Keadaan sepatutnya berubah dengan ketara jika anda memadamkan 300 juta rekod, jadi saya memutuskan untuk berbuat demikian... Eh, saya fikir ini pasti berkesan.

Tindakan 1

Setelah menyediakan sandaran yang boleh dipercayai, akhirnya saya mula menghantar permintaan.

γ€ŒMenghantar permintaan」

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

"…"

"…"

β€œHmm... Tiada jawapan. Mungkin prosesnya mengambil masa yang lama?” β€” Saya fikir, tetapi untuk berjaga-jaga, saya melihat grafana dan melihat bahawa beban cakera berkembang sangat cepat.
"Berbahaya," saya berfikir lagi dan segera menghentikan permintaan itu.

Tindakan 2

Selepas menganalisis segala-galanya, saya menyedari bahawa jumlah data terlalu besar untuk memadamkan semuanya sekaligus.

Saya memutuskan untuk menulis skrip yang boleh memadamkan kira-kira 1 rekod dan melancarkannya.

γ€ŒSaya melaksanakan skrip」

"Sekarang ini pasti akan berjaya," saya fikir.

Tindakan 3

Kaedah kedua berkesan, tetapi ternyata sangat intensif buruh.
Untuk melakukan segala-galanya dengan berhati-hati, tanpa saraf yang tidak perlu, akan mengambil masa kira-kira dua minggu. Namun begitu, senario ini tidak memenuhi keperluan perkhidmatan, jadi kami terpaksa beralih daripadanya.

Jadi inilah yang saya memutuskan untuk lakukan:

Salin jadual dan namakannya

Daripada langkah sebelumnya, saya menyedari bahawa memadamkan sejumlah besar data menghasilkan beban yang sama besar. Jadi saya memutuskan untuk mencipta jadual baharu dari awal menggunakan sisip dan alihkan data yang akan saya padamkan ke dalamnya.

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

Jika anda membuat jadual baharu dengan saiz yang sama seperti di atas, kelajuan pemprosesan data juga harus menjadi 1/7 lebih pantas.

Selepas mencipta jadual dan menamakannya semula, saya mula menggunakannya sebagai jadual induk. Sekarang jika saya menjatuhkan jadual dengan 300 juta rekod, semuanya akan baik-baik saja.
Saya mendapati bahawa truncate atau drop menghasilkan lebih sedikit overhed daripada memadam dan memutuskan untuk menggunakan kaedah ini.

pelaksanaan

γ€ŒMenghantar permintaan」

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

"…"
"…"
"Em…?"

Tindakan 4

Saya fikir idea sebelumnya akan berfungsi, tetapi selepas menghantar permintaan sisipan, berbilang ralat muncul. MySQL tidak memaafkan.

Saya sudah terlalu letih sehingga saya mula berfikir bahawa saya tidak mahu melakukan ini lagi.

Saya duduk dan berfikir dan menyedari bahawa mungkin terdapat terlalu banyak pertanyaan sisipan untuk satu masa...
Saya cuba menghantar permintaan sisipan untuk jumlah data yang perlu diproses oleh pangkalan data dalam 1 hari. Terjadi!

Nah, selepas itu kami terus menghantar permintaan untuk jumlah data yang sama. Memandangkan kami perlu mengalih keluar data bernilai sebulan, kami mengulangi operasi ini kira-kira 35 kali.

Menamakan semula jadual

Di sini nasib menyebelahi saya: semuanya berjalan lancar.

Makluman hilang

Kelajuan pemprosesan kelompok telah meningkat.

Sebelum ini proses ini mengambil masa kira-kira sejam, kini mengambil masa lebih kurang 2 minit.

Selepas saya yakin bahawa semua masalah telah diselesaikan, saya menjatuhkan 300 juta rekod. Saya memadamkan jadual dan berasa dilahirkan semula.

Ringkasan

Saya menyedari bahawa pemprosesan putaran tiada dalam pemprosesan kelompok, dan itu adalah masalah utama. Kesilapan seni bina seperti ini membawa kepada pembaziran masa.

Adakah anda berfikir tentang beban semasa replikasi data apabila memadam rekod daripada pangkalan data? Jangan membebankan MySQL.

Mereka yang mahir dalam pangkalan data pasti tidak akan menghadapi masalah seperti itu. Untuk anda yang lain, saya harap artikel ini berguna.

Terima kasih untuk membaca!

Kami akan sangat gembira jika anda memberitahu kami sama ada anda menyukai artikel ini, sama ada terjemahannya jelas, sama ada ia berguna kepada anda?

Sumber: www.habr.com

Tambah komen