Jadi saya memiliki tabel audit ini (melacak tindakan pada tabel apa pun di database saya):
CREATE TABLE `track_table` (
`id` int(16) unsigned NOT NULL,
`userID` smallint(16) unsigned NOT NULL,
`tableName` varchar(255) NOT NULL DEFAULT '',
`tupleID` int(16) unsigned NOT NULL,
`date_insert` datetime NOT NULL,
`action` char(12) NOT NULL DEFAULT '',
`className` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `userID` (`userID`),
KEY `tableID` (`tableName`,`tupleID`,`date_insert`),
KEY `actionDate` (`action`,`date_insert`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
dan saya harus mulai mengarsipkan item yang sudah ketinggalan zaman. Tabel telah berkembang menjadi sekitar 50 juta baris, jadi cara tercepat saya bisa menghapus baris adalah menghapusnya dalam satu waktu (berdasarkan pada tableName
).
Ini berfungsi cukup baik tetapi pada beberapa tabel yang berat, itu tidak akan lengkap. Kueri saya menghapus semua item yang memiliki delete
tindakan terkait pada kombinasi tupleID / tableName:
DELETE FROM track_table WHERE tableName='someTable' AND tupleID IN (
SELECT DISTINCT tupleID FROM track_table
WHERE tableName='someTable' AND action='DELETE' AND date_insert < DATE_SUB(CURDATE(), INTERVAL 30 day)
)
Saya membiarkan ini berjalan di server saya selama 3 hari dan tidak pernah selesai untuk tabel terbesar. Hasil penjelasan (jika saya mengganti hapus untuk memilih:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | PRIMARY | track_table | ref | tableID | tableID | 257 | const | 3941832 | Using where |
| 2 | DEPENDENT SUBQUERY | track_table | ref | tableID,actionDate | tableID | 261 | const,func | 1 | Using where; Using temporary |
Jadi 4 juta baris seharusnya tidak perlu 3 hari untuk dihapus, saya pikir. Saya mengatur Innodb_buffer_pool_size saya menjadi 3GB, dan server tidak diatur untuk menggunakan one_file_per_table. Apa cara lain yang bisa saya lakukan untuk meningkatkan kinerja penghapusan InnoDB? (Menjalankan MySQL 5.1.43 di Mac OSX)
sumber
Penghapusan baris yang tidak diinginkan dalam batch harus membuat operasi lain bisa berjalan. Tetapi penghapusan operasi Anda memiliki kondisi, jadi pastikan bahwa ada indeks yang sesuai pada kolom di atas kondisi.
Karena MySQL tidak mendukung fungsi lengkap longgar indeks scan, Anda dapat mencoba untuk menyesuaikan urutan untuk
KEY actionDate (action, date_insert)
untukKEY actionDate (date_insert, action)
. Dengan awalan 'date_insert', MySQL harus menggunakan indeks ini untuk memindai baris yang sebelum kondisi datetime Anda.Dengan indeks tersebut, Anda dapat menulis SQL sebagai:
sumber
-Fist, dari Anda menjelaskan key_len begitu besar => Anda perlu menurunkan ukuran sekecil mungkin. Untuk kueri Anda, saya pikir cara terbaik adalah mengubah tipe data bidang tindakan dari char (12) menjadi tinyint, sehingga pemetaan data terlihat seperti:
dan Anda dapat mengubah table_id sebagai ganti nama tab juga. DDL untuk kinerja terbaik dapat:
sehingga kueri dapat berjalan terlihat seperti:
Tetapi cara tercepat adalah menggunakan partisi. sehingga Anda dapat menjatuhkan partisi. Saat ini, meja saya sudah mendapat lebih dari 40mil baris. dan perbarui setiap jam (pembaruan 400k baris untuk setiap kali), dan saya dapat menjatuhkan partisi curr_date dan memuat ulang data ke dalam tabel. perintah drop sangat cepat (<100ms). Semoga bantuan ini.
sumber