MySQL 5.6'yı, çoğu tablo için InnoDB depolama motoruyla kullanma. InnoDB arabellek havuzu boyutu 15 GB'dir ve Innodb DB + dizinleri yaklaşık 10 GB'dir. Sunucu 32GB RAM'e sahip ve Cent OS 7 x64 ile çalışıyor.
10 milyondan fazla kayıt içeren büyük bir masam var.
Her 24 saatte bir uzak sunucudan güncelleştirilmiş bir döküm dosyası alıyorum. Dosya csv formatındadır. Bu format üzerinde kontrol sahibi değilim. Dosya ~ 750 MB'dir. Bir MyISAM tablo satır satır satır veri eklemek çalıştı ve 35 dakika sürdü.
Dosyadan 10-12 satır dışında yalnızca 3 değer alıp veritabanında güncellemem gerekiyor.
Böyle bir şeyi başarmanın en iyi yolu nedir?
Bunu günlük yapmam gerekiyor.
Şu anda Akış şöyle:
- mysqli_begin_transaction
- Dökümü dosyasını satır satır oku
- Her kaydı Satır Satır güncelleyin.
- mysqli_commit
Yukarıdaki işlemlerin tamamlanması yaklaşık 30-40 dakika sürer ve bunu yaparken bana devam eden başka güncellemeler de var.
Kilitleme bekleme zaman aşımı aşıldı; işlemi yeniden başlatmayı deneyin
Güncelleme 1
veri kullanarak yeni tabloda yükleme LOAD DATA LOCAL INFILE
. MyISAM'da InnoDB'de 38.93 sec
7 dakika 5.21 saniye sürdü. Sonra yaptım:
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)
Güncelleme 2
join sorgusu ile aynı güncelleme
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)
Yorumlardaki sorulardan açıklamalar:
- Tablodaki satırların yaklaşık% 6'sı dosya tarafından güncellenecektir, ancak bazen% 25 kadar olabilir.
- Güncellenen alanlarda indeksler var. Masada 12 dizin bulunur ve 8 dizin güncelleme alanlarını içerir.
- O değil gerekli bir işlemde güncelleştirmeyi yapmak. Zaman alabilir ancak 24 saatten fazla olamaz. Tüm masayı kilitlemeden 1 saat içinde halletmeyi düşünüyorum, daha sonra bu tabloya bağlı olan sfenks indeksini güncellemem gerekiyor. Veritabanının diğer görevler için uygun olduğu sürece adımların daha uzun sürmesi önemli değildir.
- Ön işleme adımında csv biçimini değiştirebilirim. Önemli olan tek şey hızlı güncelleme ve kilitlemesiz.
- Tablo 2, MyISAM'dir. Yükleme verilerini kullanarak csv dosyasından yeni oluşturulan tablodur. MYI dosya boyutu 452 MB'dır. Tablo 2, field1 sütununda dizine eklenmiştir.
- MyISAM tablosunun MYD'si 663 MB'dir.
Güncelleme 3:
Her iki tablo hakkında daha fazla ayrıntı.
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
ve burada content
verileri kullanarak tabloyu güncelleyen güncelleme sorgusucontent_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
güncelleme 4:
Yukarıdaki testlerin tümü test makinesinde yapıldı. Ancak şimdi üretim makinesinde de aynı testleri yaptım ve sorgular çok hızlı.
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
hatam için özür dilerim. Her kayıt güncellemesi yerine birleştirmek daha iyidir. şimdi rick_james tarafından önerilen dizini kullanarak mpre'yi geliştirmeye çalışıyorum, bench-marking yapıldıktan sonra güncellenecek.
UPDATEs
. Lütfen bize tam olarak basit deyimi görünüyor csv veri tablosunu güncellemek için ne gibi. O zaman gereksinimlerinizi karşılayan bir teknik tasarlamanıza yardımcı olabiliriz.
update
ve güncellenmiş soruyu kontrol ediniz, teşekkürler.
INDEX(field2, field3, field4)
mı? Lütfen bize gösterSHOW CREATE TABLE
.