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 TABLE
akan 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`
ALTER TABLE ... ENGINE=InnoDB;
(jika Anda punya ruang untuk melakukannya). Kebanyakan hanya puas dengan SSD mereka yang sangat cepat dan tidak akan lagi khawatir.Jawaban:
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 TABLE
saat Anda menyebutkannya, tetapi Anda harus peduli denganinnodb_file_per_table
variabelnya:Biarkan saya jelaskan:
The
OPTIMIZE TABLE
whith 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
OPTIMIZE
pernyataan 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
OPTIMIZE
proses, tabel baru Anda akan dibuat (mendekati 700GB), tetapi bahkan setelah operasi drop dan penggantian nama (dan akhirOPTIMIZE
fase) 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 TABLE
pernyataan, yangALTER TABLE
akan bekerja dengan cara yang samaOPTIMIZE TABLE
. Anda bisa menggunakan:3. ALTER TABLE (ONLINE)
Masalah
OPTIMIZE
danALTER TABLE
itu 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 besarALTER
itu keren.Perhatikan bahwa Anda harus
FOREIGN KEY
merujuk ke tabel Anda, FK, dan memicu risiko untuk menghasilkan kekacauan. Untuk memeriksa prereq ini, kueri:Inilah cara saya menggunakan pt-online-schema-change:
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.
sumber
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:
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):
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
sumber