Menggunakan MySQL 5.6 dengan mesin penyimpanan InnoDB untuk sebagian besar tabel. Ukuran buffer pool InnoDB adalah 15 GB dan indeks Innodb DB + sekitar 10 GB. Server memiliki RAM 32GB dan menjalankan Cent OS 7 x64.
Saya punya satu meja besar yang berisi sekitar 10 juta + catatan.
Saya mendapatkan file dump yang diperbarui dari server jarak jauh setiap 24 jam. File ini dalam format csv. Saya tidak memiliki kendali atas format itu. File ini ~ 750 MB. Saya mencoba memasukkan data ke tabel MyISAM baris demi baris dan butuh 35 menit.
Saya hanya perlu mengambil 3 nilai per baris dari 10-12 dari file dan memperbaruinya dalam database.
Apa cara terbaik untuk mencapai sesuatu seperti ini?
Saya perlu melakukan ini setiap hari.
Saat ini Flow seperti ini:
- mysqli_begin_transaction
- Baca file Dump baris demi baris
- Perbarui setiap catatan Baris demi Baris.
- mysqli_commit
Operasi di atas membutuhkan sekitar 30-40 menit untuk menyelesaikan dan saat melakukan ini, ada pembaruan lain yang terjadi yang memberi saya
Batas waktu tunggu tunggu melebihi; coba mulai kembali transaksi
Perbarui 1
memuat data dalam tabel baru menggunakan LOAD DATA LOCAL INFILE. Di MyISAM butuh waktu 38.93 secsementara di InnoDB butuh 7 menit 5,21 detik. Lalu saya lakukan:
UPDATE table1 t1, table2 t2
SET
t1.field1 = t2.field1,
t1.field2 = t2.field2,
t1.field3 = t2.field3
WHERE t1.field10 = t2.field10
Query OK, 434914 rows affected (22 hours 14 min 47.55 sec)
Perbarui 2
pembaruan yang sama dengan permintaan bergabung
UPDATE table1 a JOIN table2 b
ON a.field1 = b.field1
SET
a.field2 = b.field2,
a.field3 = b.field3,
a.field4 = b.field4
(14 hours 56 min 46.85 sec)
Klarifikasi dari pertanyaan dalam komentar:
- Sekitar 6% dari baris dalam tabel akan diperbarui oleh file, tetapi kadang-kadang bisa sebanyak 25%.
- Ada indeks pada bidang yang sedang diperbarui. Ada 12 indeks di atas meja, dan 8 indeks termasuk bidang pembaruan.
- Tidak perlu melakukan pembaruan dalam satu transaksi. Ini bisa memakan waktu tetapi tidak lebih dari 24 jam. Saya ingin menyelesaikannya dalam 1 jam tanpa mengunci seluruh tabel, karena nanti saya harus memperbarui indeks sphinx yang bergantung pada tabel ini. Tidak masalah jika langkah-langkah memakan waktu lebih lama selama database tersedia untuk tugas-tugas lain.
- Saya bisa memodifikasi format csv dalam langkah preprocess. Satu-satunya hal yang penting adalah pembaruan cepat dan tanpa mengunci.
- Tabel 2 adalah MyISAM. Ini adalah tabel yang baru dibuat dari file csv menggunakan memuat data infile. Ukuran file MYI adalah 452 MB. Tabel 2 diindeks pada kolom field1.
- MYD dari tabel MyISAM adalah 663MB.
Pembaruan 3:
berikut ini rincian lebih lanjut tentang kedua tabel.
CREATE TABLE `content` (
`hash` char(40) CHARACTER SET ascii NOT NULL DEFAULT '',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`og_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`keywords` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`files_count` smallint(5) unsigned NOT NULL DEFAULT '0',
`more_files` smallint(5) unsigned NOT NULL DEFAULT '0',
`files` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`category` smallint(3) unsigned NOT NULL DEFAULT '600',
`size` bigint(19) unsigned NOT NULL DEFAULT '0',
`downloaders` int(11) NOT NULL DEFAULT '0',
`completed` int(11) NOT NULL DEFAULT '0',
`uploaders` int(11) NOT NULL DEFAULT '0',
`creation_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`upload_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last_updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`vote_up` int(11) unsigned NOT NULL DEFAULT '0',
`vote_down` int(11) unsigned NOT NULL DEFAULT '0',
`comments_count` int(11) NOT NULL DEFAULT '0',
`imdb` int(8) unsigned NOT NULL DEFAULT '0',
`video_sample` tinyint(1) NOT NULL DEFAULT '0',
`video_quality` tinyint(2) NOT NULL DEFAULT '0',
`audio_lang` varchar(127) CHARACTER SET ascii NOT NULL DEFAULT '',
`subtitle_lang` varchar(127) CHARACTER SET ascii NOT NULL DEFAULT '',
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
`uploader` int(11) unsigned NOT NULL DEFAULT '0',
`anonymous` tinyint(1) NOT NULL DEFAULT '0',
`enabled` tinyint(1) unsigned NOT NULL DEFAULT '0',
`tfile_size` int(11) unsigned NOT NULL DEFAULT '0',
`scrape_source` tinyint(1) unsigned NOT NULL DEFAULT '0',
`record_num` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`record_num`),
UNIQUE KEY `hash` (`hash`),
KEY `uploaders` (`uploaders`),
KEY `tfile_size` (`tfile_size`),
KEY `enabled_category_upload_date_verified_` (`enabled`,`category`,`upload_date`,`verified`),
KEY `enabled_upload_date_verified_` (`enabled`,`upload_date`,`verified`),
KEY `enabled_category_verified_` (`enabled`,`category`,`verified`),
KEY `enabled_verified_` (`enabled`,`verified`),
KEY `enabled_uploader_` (`enabled`,`uploader`),
KEY `anonymous_uploader_` (`anonymous`,`uploader`),
KEY `enabled_uploaders_upload_date_` (`enabled`,`uploaders`,`upload_date`),
KEY `enabled_verified_category` (`enabled`,`verified`,`category`),
KEY `verified_enabled_category` (`verified`,`enabled`,`category`)
) ENGINE=InnoDB AUTO_INCREMENT=7551163 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=FIXED
CREATE TABLE `content_csv_dump_temp` (
`hash` char(40) CHARACTER SET ascii NOT NULL DEFAULT '',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`category_id` int(11) unsigned NOT NULL DEFAULT '0',
`uploaders` int(11) unsigned NOT NULL DEFAULT '0',
`downloaders` int(11) unsigned NOT NULL DEFAULT '0',
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
dan di sini adalah permintaan pembaruan yang memperbarui contenttabel menggunakan data daricontent_csv_dump_temp
UPDATE content a JOIN content_csv_dump_temp b
ON a.hash = b.hash
SET
a.uploaders = b.uploaders,
a.downloaders = b.downloaders,
a.verified = b.verified
pembaruan 4:
semua pengujian di atas dilakukan pada mesin uji., tapi sekarang saya melakukan tes yang sama pada mesin produksi, dan permintaan sangat cepat.
mysql> UPDATE content_test a JOIN content_csv_dump_temp b
-> ON a.hash = b.hash
-> SET
-> a.uploaders = b.uploaders,
-> a.downloaders = b.downloaders,
-> a.verified = b.verified;
Query OK, 2673528 rows affected (7 min 50.42 sec)
Rows matched: 7044818 Changed: 2673528 Warnings: 0
saya minta maaf atas kesalahan saya. Lebih baik menggunakan join daripada setiap pembaruan catatan. sekarang saya mencoba untuk meningkatkan mpre menggunakan indeks yang disarankan oleh rick_james, akan diperbarui setelah bench-marking selesai.
UPDATEs . Tolong beri tahu kami secara persis seperti apa pernyataan langsung untuk memperbarui tabel dari data csv. Maka kami mungkin dapat membantu Anda menemukan teknik yang memenuhi persyaratan Anda.
update, dan silakan periksa pertanyaan yang diperbarui., Terima kasih
INDEX(field2, field3, field4)(dalam urutan apa pun)? Tolong tunjukkan pada kamiSHOW CREATE TABLE.