Szybkie wstawianie danych MySql do wielu tabel.

0

Problem:
do bazy danych zapisywane są Event róznego typu. Zależnie od typu Event ma rożny zestaw danych.

Do wstawiania danych napisałem sobie procedure w takim stylu:

DROP PROCEDURE IF EXISTS storeIntegerValue;
DELIMITER $$
CREATE PROCEDURE storeIntegerValue(IN eventId BIGINT, IN pTimeStamp datetime, IN intValue BIGINT)
BEGIN
    INSERT INTO stored_integer_entries (eventId, timeStamp, intValue) VALUES (eventId, pTimeStamp, intValue);
END$$
DELIMITER ;

DROP PROCEDURE IF EXISTS storeStringValue;
DELIMITER $$
CREATE PROCEDURE storeStringValue(IN eventId BIGINT, IN pTimeStamp datetime, IN stringValue VARCHAR(255))
BEGIN
    INSERT INTO stored_strings (timeStamp, stringValue) VALUES(pTimeStamp, stringValue)
        ON DUPLICATE KEY UPDATE stringValueId=LAST_INSERT_ID(stringValueId), timeStamp=timeStamp, stringValue=stringValue;

    INSERT INTO stored_entries (eventId, timeStamp, stringValueId) VALUES(eventId, pTimeStamp, LAST_INSERT_ID());
END$$
DELIMITER ;

DROP PROCEDURE IF EXISTS storeValue;
DELIMITER $$
CREATE PROCEDURE storeValue(IN eventId BIGINT, IN pTimeStamp datetime, IN intValue BIGINT, IN stringValue VARCHAR(255))
BEGIN
  IF stringValue IS NULL THEN
    CALL storeIntegerValue(eventId, pTimeStamp, intValue);
  ELSE
    CALL storeStringValue(eventId, pTimeStamp, stringValue);
  END IF;
END$$
DELIMITER ;

Potem wczytuje wyrażenie sql storeValue(?, ?, ?, ?) wywołuje z odpowiednimi parametrami dla każdego Event (zawsze jedno jest z intValue stringValue jest puste NULL).
To działa poprawnie, ale nie jest najlepszym rozwiązaniem, szczególnie że danych może być bardzo dużo podczas zapisu i wydajność jest bardzo ważna.

Przyznam się szczerze, że pierwszy raz robię coś bardziej zakręconego z bazami danych.

Czy jest jakaś lepsza metoda dodawania danych do kilku table (na których przy odczycie będzie robiony join), która będzie bardziej wydajna?

To, że kod logiki biznesowej jest w C++17 to raczej nie ma znaczenia.

0

Bez znajomości modelu danych i pozostałej logiki niewiele można powiedzieć. W samych insertach nie ma nic szczególnego czym można się przejmować.

0

A nie możesz wywołać tego jakimś batch query? O ile twoja procedura nie zwraca nic poza liczbą zmienionych rowów to powinno się dać.

1

najważniejsze przy większej ilości insertów na raz jest to aby grupować je np. po 100 - 1000 w jedną transakcję. Jeśli puszczasz np. 1000 insertów jeden po drugim i każdy jest w osobnej transakcji to jest to przynajmniej o rząd wielkości wolniejsze. Możesz też rozważyć wyłączenie indeksów na czas insertów i przebudowanie ich po wstawieniu danych. Jednak to się będzie opłacało dopiero od pewnej wielkości paczki no i jeśli przyjdzie Ci w tym czasie select to nie skorzysta z indeksów.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.