2017-04-22 2 views
0

、構造は次のとおりです。どのインデックスがクエリをスピードアップしますか? 3.5億レコードのテーブルで

CREATE TABLE `table` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `job_id` int(10) unsigned NOT NULL, 
    `lock` mediumint(6) unsigned DEFAULT '0', 
    `time` timestamp NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `job_id` (`job_id`), 
    KEY `lock` (`lock`), 
    KEY `time` (`time`) 
) ENGINE=MyISAM; 

私は、クエリスピードアップするために作成する必要がありますどのようなインデックス:このクエリの

UPDATE `table` SET `lock` = 1 WHERE `lock` = 0 ORDER BY `time` ASC LIMIT 500; 
+0

なぜMyISAMを使用しますか?このクエリを頻繁に実行すると、MyISAMにはテーブルロックしかありません。これは、他の誰も実行していないこのクエリ(または他の書き込み)がこのテーブル –

+0

@BerndBuffenを読み書きできるとき、あなたは何を使用するようアドバイスしますか? – Dmitry

+0

関連のないデータベースタグは使用しないでください。 –

答えて

0

UPDATE `table` 
    SET `lock` = 1 
    WHERE `lock` = 0 
    ORDER BY `time` ASC 
    LIMIT 500; 

を最良のインデックスはtable(lock, time)です。ただし、アップデートでもインデックスを更新する必要があるので、実際にどのようにうまく動作しているかをテストする必要があります。これをクラスタ化インデックスにしないでください。それだけでプロセスが遅くなります。

+0

このキーは非常に長く働きます。要求が同じインデックスの更新につながるという事実のためであると思われる。 – Dmitry

1

lockは、NULLableと宣言されています。これは、値がしばしばNULLであることを意味しますか?もしそうなら、MyISAM(InnoDBではなく)に500の追加の断片化ヒットを引き起こす恐ろしい問題があります。

MyISAM行が更新されると、は長くなり、その行はどこにも適合しなくなります。 (今、私の詳細な知識は曖昧になります。)新しい行は別の場所に置かれ、2つの部分に分割され、部分間のリンクが付けられます。それは2つの場所での書き込みを意味します。

あなたのケースでは、インデックス化された列であるlockを変更すると、インデックスの更新が必要になります。インデックスのBTreeの1か所から '行'を削除し、別の場所に行を追加します。

lockには0または1の値しかありませんか?次に、MEDIUMINT(3バイト)ではなく、TINYINT(1バイト)を使用します。

MAX(id)をチェックしてください。それがきれいであれば、IDの最大値は約350Mになります(4Bの限界にあまり近くない)。しかし、チャーンがあった場合は、限界にはるかに近いかもしれません。

私もInnoDBへの切り替えを勧めます。ただし、変換では10GB(データ+インデックス)が20-30GBに増加します。

"ロックされている最古のロックされていない"ものはロックしていますか?何がロックされているかを見るためにselectを実行しますか?

これが遅すぎる場合は、すぐに500を実行しないでください。小さい番号を選択してください。

InnoDBを使用すると、ロックを回避できますか? おそらくトランザクションロックで十分でしょうか?

他のテーブル、ジョブ "フロー"などの残りの環境を確認する必要があると思います。私たちが提案できる他のものもあります。

そして、私はINDEX(lock, time)の動きの2番目です。しかしそうするときには、DROPのインデックスはちょうどlockに重複しています。

InnoDBに変換するときは、のすべてのインデックス変更を同じALTERにしてください。これは別々のパスよりも速く実行されます。

+0

あなたの答えをありがとう、私はInnoDBにテーブルを転送し、SQLクエリのテストを実施しようとします。 – Dmitry

関連する問題