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 sec
sementara 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 content
tabel 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
.