Używanie MySQL 5.6 z silnikiem pamięci InnoDB dla większości tabel. Wielkość puli buforów InnoDB wynosi 15 GB, a indeksy Innodb DB + wynoszą około 10 GB. Serwer ma 32 GB pamięci RAM i działa w systemie Cent OS 7 x64.
Mam jeden duży stół, który zawiera około 10 milionów + rekordów.
Otrzymuję zaktualizowany plik zrzutu ze zdalnego serwera co 24 godziny. Plik ma format csv. Nie mam kontroli nad tym formatem. Plik ma rozmiar ~ 750 MB. Próbowałem wstawiać dane do tabeli MyISAM wiersz po rzędzie i zajęło to 35 minut.
Muszę pobrać tylko 3 wartości na linię z 10-12 z pliku i zaktualizować go w bazie danych.
Jaki jest najlepszy sposób na osiągnięcie czegoś takiego?
Muszę to robić codziennie.
Obecnie Flow wygląda następująco:
- mysqli_begin_transaction
- Czytaj zrzut pliku linia po linii
- Zaktualizuj każdy rekord linia po linii.
- mysqli_commit
Powyższe operacje trwają około 30-40 minut, a przy tym trwają inne aktualizacje, które dają mi
Przekroczono limit czasu oczekiwania na zablokowanie; spróbuj ponownie uruchomić transakcję
Aktualizacja 1
ładowanie danych w nowej tabeli za pomocą LOAD DATA LOCAL INFILE
. W MyISAM zajęło to 38.93 sec
w InnoDB 7 min. 5,21 sek. Potem zrobiłem:
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)
Aktualizacja 2
ta sama aktualizacja z zapytaniem dołączenia
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)
Wyjaśnienia na podstawie pytań w komentarzach:
- Plik zaktualizuje około 6% wierszy w tabeli, ale czasem może to być nawet 25%.
- Są aktualizowane indeksy pól. Tabela zawiera 12 indeksów, a 8 indeksów zawiera pola aktualizacji.
- Aktualizacja nie jest konieczna w ramach jednej transakcji. Może to zająć trochę czasu, ale nie więcej niż 24 godziny. Chcę to zrobić w ciągu 1 godziny bez blokowania całej tabeli, ponieważ później muszę zaktualizować indeks sfinksa, który jest zależny od tej tabeli. Nie ma znaczenia, czy kroki trwają dłużej, o ile baza danych jest dostępna dla innych zadań.
- Mógłbym zmodyfikować format csv w kroku wstępnego przetwarzania. Liczy się tylko szybka aktualizacja i bez blokowania.
- Tabela 2 to MyISAM. Jest to nowo utworzona tabela z pliku csv przy użyciu pliku danych ładowania. Rozmiar pliku MYI wynosi 452 MB. Tabela 2 jest indeksowana w kolumnie field1.
- MYD tabeli MyISAM wynosi 663 MB.
Aktualizacja 3:
oto więcej szczegółów na temat obu 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
a oto zapytanie o aktualizację, które aktualizuje content
tabelę przy użyciu danych zcontent_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
aktualizacja 4:
wszystkie powyższe testy przeprowadzono na maszynie testowej., ale teraz zrobiłem te same testy na maszynie produkcyjnej, a zapytania są bardzo szybkie.
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
Przepraszam za mój błąd. Lepiej używać łączenia zamiast każdej aktualizacji rekordu. teraz próbuję ulepszyć mpre przy użyciu indeksu sugerowanego przez rick_james, zaktualizuje się po zakończeniu benchmarkingu.
UPDATEs
. Powiedz nam dokładnie, jak wygląda prosta instrukcja do aktualizacji tabeli z danych csv. W takim razie możemy pomóc Ci w opracowaniu techniki spełniającej Twoje wymagania.
update
i sprawdź zaktualizowane pytanie., Dzięki
INDEX(field2, field3, field4)
(w dowolnej kolejności)? Proszę nam pokazaćSHOW CREATE TABLE
.