このようなテーブルがあります
CREATE TABLE IF NOT EXISTS `dnddata` (
`numbers` varchar(10) NOT NULL,
`opstype` char(1) NOT NULL,
PRIMARY KEY (`numbers`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY KEY (numbers)
PARTITIONS 25 */;
3億件のレコードを挿入する必要があります。 csvファイルからload data in file
を使用して毎回1000万レコードを挿入しています。
最初に5分近くかかって1000万件のレコードを挿入する。時間は徐々に増加しています。 3000万件のレコードの後、挿入が停止し、100%サーバーを使用してメモリが応答しなくなります。
my.cnf
ファイル設定の下
bulk_insert_buffer_size = 100M
key_buffer = 100M
sort_buffer_size = 50M
read_buffer = 50M
2 GメモリのCPUを使用しています。
3000万レコードの詳細
Space usage
Type Usage
Data 545.3 MiB
Index 694.8 MiB
Total 1,240.1 MiB
MySQL client version: 5.5.14
インデックスなしでは、50秒で1,000万回挿入されます。
どのような設定を変更する必要があるか教えてください。
ユーザーの回答に基づいて編集
My.cnf設定を以下に変更しました
key_buffer_size = 1G
sort_buffer_size = 4M
read_buffer_size = 1M
read_rnd_buffer_size = 1M
join_buffer_size = 2M
bulk_insert_buffer_size = 32M
myisam_sort_buffer_size = 256M
無駄だ。問題は解決されていません。
以下の方法でデータをロードしました
set autocommit = 0; //for innodb
load data infile into …
COMMIT;
START TRANSACTION;
load data infile into …
COMMIT;
ALTER TABLE dnddata DISABLE KEYS;
load data infile into …
ALTER TABLE dnddata ENABLE KEYS;
運が悪い.
データの読み込みを高速化するには、このような巨大なファイルをチャンクで読み込む必要があります。ここでは、巨大なLoad local data
ファイルの読み込みに関する問題と、それを解決して高速化する方法について説明します。
テーブルに多くのインデックスがある場合、MyISAMテーブルの追加の作業により、LOAD DATA INFILE
をさらに高速に実行できます。
FLUSH TABLESステートメントまたはmysqladmin flush-tablesコマンドを実行します。
Myisamchk --keys-used = 0 -rq/path/to/db/tbl_nameを使用して、テーブルのインデックスの使用をすべて削除します。
LOAD DATA INFILEを使用してデータをテーブルに挿入します。これはインデックスを更新しないため、非常に高速です。
myisamchk -rq /path/to/db/tbl_name
を使用してインデックスを再作成します。これにより、ディスクに書き込む前にメモリにインデックスツリーが作成されます。これにより、大量のディスクシークが回避されるため、LOAD DATA INFILE中にインデックスを更新するよりもはるかに高速になります。結果のインデックスツリーも完全にバランスが取れています。
FLUSH TABLESステートメントまたはmysqladmin flush-tablesコマンドを実行します。
LOAD DATA INFILEは、データを挿入するMyISAMテーブルが空の場合、前述の最適化を自動的に実行します。自動最適化とプロシージャを明示的に使用することの主な違いは、サーバーがLOAD DATA INFILEステートメントを実行するときにインデックスの再作成に割り当てるよりも、myisamchkにインデックスの作成用にはるかに多くの一時メモリを割り当てることができることです。
Myisamchkではなく次のステートメントを使用して、MyISAMテーブルの一意でないインデックスを無効または有効にすることもできます。これらのステートメントを使用する場合、FLUSH TABLE操作をスキップできます。
ALTER TABLE tbl_name DISABLE KEYS;
ALTER TABLE tbl_name ENABLE KEYS;
詳細については、以下を参照してください。
http://dev.mysql.com/doc/refman/5.5/en/optimizing-myisam-bulk-data-loading.html
CREATE TABLE
コマンドにインデックスがありませんでした(主キー以外)。問題から除外しただけで実際に存在する場合は、LOAD DATA
コマンドの前にインデックスを無効にして、完了後に再構築できます。
ALTER TABLE dnddata DISABLE KEYS;
LOAD DATA INFILE ... ;
ALTER TABLE dnddata ENABLE KEYS;
テーブルが大きくなると、インデックスを書き込む時間が長くなります。
MyISAMテーブルを扱っているので
CREATE TABLE dndtemp ENGINE=MyISAM SELECT * FROM dnddata WHERE 1=2;
LOAD DATA INFILE ... INTO TABLE dndtemp ... ;
INSERT INTO dnddata SELECT * FROM dndtemp;
DROP TABLE dndtemp;
一時テーブルにはインデックスがないため、LOAD DATA INFILE
の方が高速です。
DISABLE KEYS
/ENABLE KEYS
は、セカンダリインデックスがないため、このインスタンスでは役に立ちません。
MyISAMインデックスの合計は694.8 MiB
であり、MyISAMはインデックスページのみをキャッシュするため、キーバッファーは今のところ768Mにサイズ変更できます。
試してみる !!!
MyISAMテーブルの一括読み込みに対応するため、 bulk_insert_buffer_size を512Mに増やす必要があります。 bulk_insert_buffer_sizeのMySQLドキュメントによると:
MyISAMは特別なツリーのようなキャッシュを使用して、空でないデータをデータに追加するときに、INSERT ... SELECT、INSERT ... VALUES(...)、(...)、...、およびLOAD DATA INFILEの一括挿入を高速化します。テーブル。この変数は、スレッドあたりのバイト数でキャッシュツリーのサイズを制限します。 0に設定すると、この最適化が無効になります。デフォルト値は8MBです。
これと、2 GBのRAM=(DBが今でも存続する方法は?)
[mysqld]
bulk_insert_buffer_size=512M
key_buffer_size=512M
IMHO、2GBのRAMは、MySQLが3000万行を効率的に処理するには不十分です。
それでも、key_bufferが小さすぎます。このボックスが専用のデータベースボックスで、2G RAMしかない場合は、安全に最大1Gにして、ディスクに頻繁にスワップしないでください。
key_buffer = 1GB