Piszę aplikację, która musi wypłukiwać dużą liczbę aktualizacji bazy danych przez dłuższy okres czasu, i utknąłem przy tym, jak zoptymalizować zapytanie. Obecnie używam INSERT INTO ... VALUES (..), (..) ON DUPLICATE KEY UPDATE
, który działa, aby spakować wszystkie wartości do jednego zapytania, ale wykonuje się niesamowicie wolno na dużych tabelach. W rzeczywistości nigdy nie muszę wstawiać wierszy.
Inne podejścia, które widziałem, to aktualizacja przy użyciu SET value = CASE WHEN...
(co byłoby trudne do wygenerowania ze względu na sposób, w jaki buduję zapytania i nie jestem pewien co do wydajności CASE
setek / tysięcy kluczy), i po prostu wielokrotne połączenie aktualizacje. Czy którekolwiek z nich byłoby szybsze niż moja obecna metoda?
Zaskakuje mnie, że o ile wiem, nie ma idiomatycznego, skutecznego sposobu na zrobienie tego w MySQL. Jeśli naprawdę nie ma sposobu, który ON DUPLICATE KEY
byłby szybszy niż , czy warto byłoby przełączyć się na PostgreSQL i użyć jego UPDATE FROM
składni?
Wszelkie inne sugestie są również mile widziane!
Edycja: oto jedna z tabel, która jest często aktualizowana. Usunąłem nazwy kolumn, ponieważ są one nieistotne.
CREATE TABLE IF NOT EXISTS `table` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`a` bigint(20) unsigned NOT NULL DEFAULT '0',
`b` bigint(20) unsigned NOT NULL DEFAULT '0',
`c` enum('0','1','2') NOT NULL DEFAULT '0',
`d` char(32) NOT NULL,
-- trimmed --
PRIMARY KEY (`id`),
KEY `a` (`a`),
KEY `b` (`b`),
KEY `c` (`c`),
KEY `d` (`d`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Odpowiedzi:
Ponieważ używasz
InnoDB
tabel, najbardziej oczywistą optymalizacją byłoby zgrupowanie wieluUPDATE
s w transakcję.Będąc
InnoDB
silnikiem transakcyjnym, płacisz nie tylko zaUPDATE
siebie, ale także za cały narzut transakcyjny: zarządzanie buforem transakcji, dziennik transakcji, opróżnianie dziennika na dysk.Jeśli logicznie nie podoba ci się ten pomysł, spróbuj pogrupować 100-1000
UPDATE
s naraz, za każdym razem zapakowane w ten sposób:Możliwe wady:
UPDATE
s, więc możesz też chcieć trochę czasuźródło