Menghapus & merebut kembali ruang dari tabel InnoDB

14

Saya memiliki tabel InnoDB 700GB yang saya tidak akan menulis data lagi (hanya membaca). Saya ingin menghapus data lama yang dipegangnya dan mengambil kembali ruang disk tersebut (karena saya kehabisan). Bagian delete cukup mudah, karena saya memiliki indeks primer auto-inc jadi saya bisa saja mengulanginya menggunakan potongan, dan menghapus baris, tetapi itu tidak akan membawa saya kembali ke ruang kosong. Saya berasumsi OPTIMIZE TABLEakan tetapi mungkin butuh selamanya di atas meja 700GB, jadi apakah ada opsi lain yang saya abaikan?

Edit oleh RolandoMySQLDBA

Dengan asumsi tabel Anda adalah mydb.mytable, jalankan kueri berikut dan posting di sini sehingga Anda dapat menentukan ruang disk yang diperlukan untuk penyusutan tabel:

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

Kita juga perlu melihat struktur tabel, jika diizinkan.

Edit oleh Noam

Ini adalah output dari query:

datsize ndxsize tblsize
682.51 47.57 730.08

Ini adalah struktur tabel ( SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`
Noam
sumber
Apakah Anda memiliki volume disk lain untuk menangkap data saja ???
RolandoMySQLDBA
@RolandoMySQLDBA Saya punya hard drive eksternal yang bisa saya pasang. Apakah itu penting?
Noam
@RolandoMySQLDBA tetapi tentu saja ingin opsi untuk menghapus beberapa ruang tanpa perlu memiliki 700GB lagi
Noam
@RolandoMySQLDBA apakah ukuran disk tambahan menyebabkan masalah kinerja?
Aris
@ Aris mungkin tergantung pada disk dan waktu pencariannya. Saat ini, sebagian besar disk berkinerja lebih baik sekarang, tetapi apa gunanya membuang-buang siklus (bahkan berjalan sangat cepat) jika Anda memiliki kantong besar ruang disk yang jarang di meja Anda ???. Ini terutama berlaku untuk InnoDB yang biasanya diperbaiki pada 16K blok. Dengan fragmentasi internal 16K blok, Anda mungkin ingin men-defrag tabel menggunakan ALTER TABLE ... ENGINE=InnoDB;(jika Anda punya ruang untuk melakukannya). Kebanyakan hanya puas dengan SSD mereka yang sangat cepat dan tidak akan lagi khawatir.
RolandoMySQLDBA

Jawaban:

21

Ini pertanyaan yang bagus. Anda memiliki beberapa solusi tetapi meja Anda cukup besar sehingga tidak ada yang tanpa rasa sakit :)

Anda memiliki tiga solusi untuk "menyusutkan" tabel InnoDB:

1. MENGOPTIMALKAN TABEL

Anda dapat menggunakannya OPTIMIZE TABLEsaat Anda menyebutkannya, tetapi Anda harus peduli dengan innodb_file_per_tablevariabelnya:

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

Biarkan saya jelaskan:

The OPTIMIZE TABLEwhith InnoDB tabel, mengunci meja, salin data di meja yang bersih baru (yang mengapa hasilnya menyusut), menjatuhkan meja asli dan mengubah nama tabel baru dengan nama asli. Itu sebabnya Anda harus peduli untuk memiliki dua kali lipat volumetri tabel Anda yang tersedia di disk Anda (Selama operasi Anda akan membutuhkan 2x700GB).

Ketika Anda berada di innodb_file_per_table = ON. Semua tabel memiliki file data yang tepat. Jadi OPTIMIZEpernyataan itu akan membuat file data baru (~ 700GB) ketika operasi selesai, MySQL akan menjatuhkan yang asli dan mengganti nama yang baru (jadi pada akhirnya 700GB - mungkin kurang karena akan menyusut - data) dihasilkan selama operasi akan dirilis)

Ketika Anda berada di innodb_file_per_table = OFF. Semua data masuk ke satu file data: ibdata . File ini memiliki kekhasan yang menyedihkan, tidak dapat menyusut. Jadi selama OPTIMIZEproses, tabel baru Anda akan dibuat (mendekati 700GB), tetapi bahkan setelah operasi drop dan penggantian nama (dan akhir OPTIMIZEfase) ibdata Anda tidak akan merilis ~ 700GB, jadi Anda ingin membebaskan beberapa data tetapi Anda memiliki 700GB lebih, keren bukan?

2. ALTER TABEL

Anda juga dapat menggunakan ALTER TABLEpernyataan, yang ALTER TABLEakan bekerja dengan cara yang sama OPTIMIZE TABLE. Anda bisa menggunakan:

ALTER TABLE myTable EGINE=InnoDB;

3. ALTER TABLE (ONLINE)

Masalah OPTIMIZEdan ALTER TABLEitu mengunci tabel selama operasi. Anda dapat menggunakan alat Percona: pt-online-schema-change (dari Percona Toolkit: tautan ). pt-online-schema ... akan membangun mekanisme dengan pemicu dan tabel temp yang Anda izinkan tabel asli tersedia untuk dibaca dan ditulis selama operasi. Saya menggunakan alat ini untuk produksi besar ALTERitu keren.

Perhatikan bahwa Anda harus FOREIGN KEYmerujuk ke tabel Anda, FK, dan memicu risiko untuk menghasilkan kekacauan. Untuk memeriksa prereq ini, kueri:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

Inilah cara saya menggunakan pt-online-schema-change:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

Perhatikan bahwa catatan saya di innodb_file_per_table benar juga untuk solusi ini.

4. mysqldump

Solusi terakhir adalah membuat ulang semua database dari dump. Sangat panjang, tetapi sangat efisien. Perhatikan bahwa ini adalah satu-satunya solusi untuk "menyusutkan" file ibdata.

Maks.

Maxime Fouilleul
sumber
Juga di alat perkona online, opsi tabel perubahan saya akan membutuhkan 700GB ruang disk kosong?
Noam
Ya, pt-online hanya menggunakan beberapa mekanisme untuk melakukan ALTER online tetapi itu tetap membuat ALTER.
Maxime Fouilleul
@ MaximeFouilleul apakah ukuran disk tambahan menyebabkan masalah kinerja?
Aris
1

Jika Anda kekurangan ukuran disk saya sarankan Anda lakukan persis seperti yang disarankan Max dengan pt-online-schema-change (ONLINE). Saya telah berada dalam situasi yang sama dengan meja yang jauh lebih kecil (200GB) dan memilih melakukan kompresi pada saat yang sama. Sesuatu di sepanjang garis ini seharusnya bekerja:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

Ini hanya akan berfungsi jika Anda berada dalam format file barracuda dan dalam format COMPACT dari tabel. Anda juga harus mengaktifkan innodb_file_per_table. Ini dapat melakukan keajaiban pada ukuran tabel Anda terutama jika ada banyak teks dan jika Anda menggunakan KEY_BLOCK_SIZE yang lebih kecil seperti 8K atau bahkan 4K (standarnya adalah 16K). Anda juga dapat memeriksa berapa banyak ruang yang dapat Anda peroleh dari beberapa tolok ukur tentang masalah ini di blog lain tetapi dokumentasi MySQL mengiklankan 25% hingga 50% (hampir 90% bagi saya).

Perhatikan bahwa ini juga dapat memengaruhi kinerja ketika melakukan SELECT (dari dokumentasi MySQL):

Jadi, pada waktu tertentu, kumpulan buffer mungkin berisi bentuk halaman terkompresi dan tidak terkompresi, atau hanya bentuk halaman terkompresi, atau keduanya.

MySQL juga harus mengompres data ketika tidak di buffer pool. Jadi berhati-hatilah.

Ini benar-benar berfungsi dengan baik dalam kasus saya. Saya memiliki teks yang panjang. 200GB menjadi 26GB. Pertunjukan tidak diubah.

Untuk info lebih lanjut, periksa tautan ini:

https://dev.mysql.com/doc/refman/5.5/id/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/id/innodb-compression-internals.html

Pemburu Emerik
sumber