2016-08-18 7 views
-1

私はと呼んでaccumulatorsを表すいくつかのデータを生成するイベントがあります。アキュムレータをゼロから作成することは、アキュムレータを既存のアタッチメントと比較しようとするよりもずっと速く実行することが分かりました。したがって、私はそれらにtransaction_idを与え、それらを作成してから、1つのクエリで以前のトランザクションを削除します。速い挿入、遅い削除、間違ったインデックス

テーブル内の200万行には約40秒が必要ですが、削除には現在以下のクエリを使用して約20〜30分かかります。

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

innodbの状態を見ると、クエリが実行されているときに次のように表示されます。私が理解できる限り、この段階では矛盾するロックがないようです。

---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 

accumulator表は以下の通り定義されています。 IDX_accumulator5ではなく、transaction_idが含まれていないIDX_accumulator3を使用していることに気付きました。

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; 

私はCentOSの7上のMySQL 5.7.13を実行している私は、スワップメモリ​​を使用し、10ギガバイトの空きメモリが残りについては持っていないが、6ギガバイトはINNODBバッファに割り当てられています。 my.cnfでのInnoDBの設定は次のとおりです。

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

あなたは行2.000.000を削除する必要があると言っています..? – scaisEdge

+0

タイトルは詩のように読まれます:D –

答えて

1

私は(!TRANSACTION_ID = @transaction_id)否定述語を解決するためにインデックスを使用する任意のDBMSを認識していませんよ。

新しいレコードを追加する理由がわかりません次に、古いものを削除するです。それ以外の方法で(テーブルを切り捨てて)行うと、少し時間がかかります。データを確実に元に戻したい場合は、既存のテーブルの名前を変更し、新しいデータを保持する新しいテーブルを作成します(元の名前で)。

+0

私はテーブルを切り捨て、あなたが提案したものを正確に実行すると考えましたが、私は複数のaccaセットを持ち、テーブルの名前を完全に変更することはできません。また、新しいセットを生成したら、別の計算を新しいtransaction_idを使用するように切り替える必要があります。これは、1つのトランザクションでは実行できないさまざまな理由からです。 – Hans

+1

古いデータタブブルの結合体のビューを作成したくないと仮定すると(パフォーマンスが吸うと意味をなさない)、状態属性(トリガーで駆動する可能性があります)を使用できます。 – symcbean

+0

別のテーブル私はすべての取引とそのステータスを記録します。私は、期限切れのトランザクションを削除するためにこれを使用し、否定ではなく、一致するレコードを '= @ transaction_id'で特定することができます。 – Hans

関連する問題