大量のデータを含むテーブルで、自動インクリメント整数とGUID(v4)の間の挿入のパフォーマンスをテストしています。これに続く ブログ投稿 、私は違いが出てくることを期待していました。しかし、現在は600万行を超えるため、違いはありません。これらは私のテーブルの定義です:
自動増加
CREATE TABLE `auto` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`))
GUID
CREATE TABLE `guid` (
`id` CHAR(32) NOT NULL,
PRIMARY KEY (`id`))
コードは参照先のブログ投稿と同じで、1つのトランザクションに10万行を数回挿入します。以前に600万行を超える行で述べたように、パフォーマンスに違いはなく、実際には同じです。私はその理由を理解しようとしています。スクリプトはC#yにあり、GUIDはアプリケーションで生成されています(MySqlではありません)。より明確にするために、1から1Mまでのforループは、 DBに挿入し、10万行に達するたびにトランザクションをコミットし、コミット時の経過時間を測定します。
私のハードウェア:Mac mini i5 2.3 GHz、16 GB Ram、960 GB SSD、ただしスクリプトはWindows 10 x64の4 GBのRAMを備えたFusion仮想マシンで実行されています、仮想マシンにインストールされているMySqlサーバー。
MySqlバージョン:5.7
だから、私は何かが足りないのですか?さらにデータが必要ですか?.
前もって感謝します。
不足しているのは、innodb_buffer_pool_size
の設定(InnoDBを使用している場合)、およびid
のインデックスのサイズとの比較です。必要な「より多くのデータ」:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW TABLE STATUS LIKE 'guid';
id
がAUTO_INCREMENT
または何らかの「増加」タイムスタンプの場合、すべての作業はインデックスの「最後の」ブロックで行われます。したがって、I/Oを回避するためにキャッシュする必要はほとんどありません。
id
がuuid/guid/md5/etcの場合、使用されるキャッシュスペース(buffer_pool)はテーブルが大きくなるにつれて大きくなります。これは、IDが「ランダムに」ジャンプしているためです。パフォーマンスに大きな影響はありませんntil buffer_poolは十分な大きさではありません。その後、物事は徐々にファンを襲った。
さらに物を運びましょう... 100万のエントリを保持できるbuffer_poolがあるとしましょう。ただし、20Mのエントリがあります。次の行が挿入される場合、1M/20Mの確率で、目的のブロックが現在buffer_poolにキャッシュされています。つまり、わずか5%です。または、「ミス」の可能性は95%です。ほとんどの場合、ディスクヒットが必要です。 I/Oは、SQLが遅くなる主な原因です。
詳細な議論: http://mysql.rjweb.org/doc.php/uuid
結論:hugeテーブルがある場合、それがPRIMARY KEY
であろうと他のインデックスであろうと、guidsはパフォーマンスを低下させます。