2016-08-18 7 views
-1

Ich habe ein Ereignis, das einige Daten erzeugt, die accumulators in was ich ein transaction nennen. Es stellte sich heraus, dass es viel schneller lief und den Akku von Grund auf neu erzeugte, als zu versuchen, sie mit bestehenden zu vergleichen. Deshalb habe ich ihnen eine transaction_id gegeben, sie erstellen und dann in einer Abfrage die vorherigen Transaktionen löschen.Mysql schnell einfügen, langsam löschen, falscher Index

Erstellung von ca. 2 Millionen Zeilen in der Tabelle benötigen ungefähr 40 Sekunden, aber das Löschen dauert derzeit ungefähr 20-30 Minuten mit der folgenden Abfrage.

DELETE 
    FROM accumulator 
WHERE id_acca_set = @set_id 
    AND (transaction_id != @transaction_id or transaction_id is null); 

Mit Blick auf den innodb-Status sehe ich Folgendes, wenn die Abfrage ausgeführt wird. Soweit ich herausfinden kann, scheint es zu diesem Zeitpunkt keine widersprüchliche Sperre zu geben.

---TRANSACTION 11535589892, ACTIVE 259 sec updating or deleting, thread declared inside InnoDB 4657 
mysql tables in use 1, locked 1 
29009 lock struct(s), heap size 3776720, 1195753 row lock(s), undo log entries 1195753 
MySQL thread id 108262, OS thread handle 131874376460032, query id 9689717638 event_scheduler updating 

Die Tabelle accumulator ist wie folgt definiert. Ich habe festgestellt, dass es nicht IDX_accumulator5 sondern IDX_accumulator3 verwendet, die nicht die transaction_id stattdessen enthält.

CREATE TABLE acca.accumulator (
id bigint(20) NOT NULL AUTO_INCREMENT, 
id_acca_set int(1) NOT NULL DEFAULT 0, 
id_event bigint(20) NOT NULL DEFAULT 0, 
id_back_outcome bigint(20) NOT NULL DEFAULT 0, 
id_lay_outcome bigint(20) NOT NULL DEFAULT 0, 
acca_id varchar(255) DEFAULT NULL, 
prev_acca_id varchar(255) DEFAULT NULL, 
leg_number int(11) NOT NULL, 
score double DEFAULT NULL, 
transaction_id varchar(255) DEFAULT NULL, 
PRIMARY KEY (id), 
INDEX IDX_accumulator (id_acca_set, acca_id, transaction_id), 
INDEX IDX_accumulator2 (id_acca_set, leg_number, acca_id, transaction_id), 
INDEX IDX_accumulator3 (id_acca_set, id_event, id_back_outcome, id_lay_outcome, leg_number), 
INDEX IDX_accumulator4 (id_acca_set, prev_acca_id, id_event), 
INDEX IDX_accumulator5 (id_acca_set, transaction_id), 
INDEX IDX_accumulator6 (transaction_id, id_acca_set, leg_number, score) 
) 
ENGINE = INNODB 
AUTO_INCREMENT = 242051170 
AVG_ROW_LENGTH = 282 
CHARACTER SET utf8 
COLLATE utf8_general_ci 
ROW_FORMAT = DYNAMIC; 

Ich bin mit MySQL 5.7.13 auf CentOS 7. Ich habe keinen Swap-Speicher verwenden und haben über 10 GB freien Speicher verbleiben, werden 6GB im InnoDB Zwischenspeicher zugeordnet. InnoDB Einstellungen in my.cnf sind:

innodb_buffer_pool_size = 6G 
innodb_buffer_pool_instances = 6 
innodb_commit_concurrency = 4 
innodb_flush_method = O_DIRECT 
innodb_thread_concurrency = 8 
innodb_thread_sleep_delay = 100 
innodb_flush_log_at_trx_commit = 1 
innodb_flush_log_at_timeout = 10 
+0

Sie sagen, dass Sie löschen müssen 2.000.000 Zeilen ..? – scaisEdge

+0

Titel liest sich wie ein Gedicht: D –

Antwort

1

Ich bin nicht bekannt, dass DBMS, die einen Index verwenden, wird eine negierte Prädikat (TRANSACTION_ID = @transaction_id!) Zu lösen.

Ich verstehe nicht, warum Sie die neuen Datensätze hinzufügen dann löschen die alten. Wenn Sie es andersherum machen (die Tabelle abschneiden), dauert es eine winzige Zeit. Wenn Sie sicherstellen möchten, dass Sie über Daten verfügen, auf die Sie zurückgreifen können, besteht ein alternativer Ansatz darin, die vorhandene Tabelle umzubenennen und dann eine neue (mit dem ursprünglichen Namen) zu erstellen, um die neuen Daten zu speichern.

+0

Ich überlegte, die Tabelle abzukürzen und genau das zu tun, was Sie vorschlagen, aber ich habe mehrere Accasets und kann die Tabelle nicht einfach komplett umbenennen. Auch wenn ich einen neuen Satz erstellt habe, muss ich eine andere Berechnung wechseln, um die neue Transaktions-ID zu verwenden, die ich aus verschiedenen Gründen nicht in einer Transaktion ausführen kann. – Hans

+1

Angenommen, Sie wollen keine Ansicht einer Union der alten Daten Tables erstellen (was bei Performance Sinn macht würde saugen) könnten Sie ein Zustandsattribut verwenden (die von einem Trigger ausgelöst werden könnte) – symcbean

+0

Ich landete mit einer anderen Tabelle wo ich alle Transaktionen und ihren Status protokolliere. Ich benutze das jetzt, um abgelaufene Transaktionen zu löschen und kann übereinstimmende Datensätze mit einer '= @ transaction_id' anstelle der Negation lokalisieren. – Hans

Verwandte Themen