Mysql 5.1xがパッケージ経由でインストールされたUbuntu 10.04を実行しているサーバーがあります。システムには128 GBのRAM、8コアがあり、MysqlとMysql tmpが保存されている4 TBの空き領域があります。
私はこのようなMyISAMを持っています:
CREATE TABLE `data_store` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`uniqname` varchar(150) NOT NULL,
`data` blob,
PRIMARY KEY (`id`)
) ENGINE=MyISAM CHARSET=latin1;
800milのレコード(挿入前に約350GBのデータ)を挿入してから、次のインデックスを追加しようとしました。
ALTER TABLE data_store DISABLE KEYS;
ALTER TABLE data_store ADD INDEX uniqname_index (uniqname);
ALTER TABLE data_store ENABLE KEYS;
(DISABLE KEYS
コマンドに関しては、データを挿入する前に他の場所で使用することをお勧めします。また、コマンドがENABLE KEYS
に到達しなかったので、私はそれが私にとっては役に立たないと想定しています。主に、私がやっていることの私の説明を徹底するために)
インデックスジョブを開始すると、SHOW PROCESSLIST
に表示される最初のステータスは「tmp tableへのコピー」です。
数時間後、bacを確認しましたが、24時間後でも「Repair With Keycache」メッセージにステータスが残ります。少し古いサーバーでジョブを実行してみましたが、3日後もステータスが「Repair with keycache」のままです。このため、この新しいマシンでcreate-indexコマンドをキャンセルしました。
「Keycacheでの修復」は非常に遅くなる可能性があることを読みました。多くの場合、「並べ替えによる修復」が推奨されます。
Stack Exchangeとオンラインのランダムな投稿に基づいて、Mysqlサーバーに次の設定を追加しました。
myisam_sort_buffer_size = 80G
bulk_insert_buffer_size = 80G
myisam_repair_threads = 8
max_heap_table_size = 20G
myisam_max_sort_file_size = 500G
tmp_table_size = 20G
key_buffer_size = 20G
sort_buffer_size = 20G
join_buffer_size = 20G
ジョブを再起動すると、同じプロセスが再び発生しました(tmpファイルにコピーしてから、キーキャッシュを介して修復します)。
ジョブを中止した後、mysql/error.logで「myisam_sort_buffer_sizeが小さすぎます」というメッセージが表示されます。これはその日の早い段階で発生したものであり、私が仕事を殺したときとは異なります。
質問
私はこの間違ったやり方をしているのですか?何らかのキー(uniqname)でデータをすばやく検索できるようにしたいだけです。
テーブルを最初からやり直し、インデックスを最初から追加し、DISABLE KEYS
コマンドを使用して800milレコードを挿入してから、ENABLE KEYS
を使用するメリットはありますか?これがtmpテーブルのコピーを妨げる可能性があることを他の場所で読みました(数時間しか節約できない可能性がありますか?)
この「並べ替えによる修復」が必要ですか?
まず、バッファサイズにはまだ触れません。あなたが質問で持っているサイズは、途方もなく大きすぎます。
次に、別の所見を示します。BLOBデータがあります。痛い、あなたの一時テーブルはスペースをかなり早く食べるでしょう。あなたはこのような何かをすることができます:
この行を/ etc/fstabに追加して、32GB RAM/var/tmpfsというディスクを作成します
none /var/tmpfs tmpfs defaults,size=32g 1 2
次に、/ mysqltmpというフォルダーを作成し、RAMディスクをその上にマウントします
mkdir /mysqltmp
chown mysql:mysql /mysqltmp
mount /mysqltmp /var/tmpfs
これをmy.cnfに追加し、mysqlを再起動します
[mysqld]
tmpdir=/mysqltmp
これで、DDL経由で作成されたすべてのtmpテーブルがRAMディスクに配置されます。
次に、別の観察を示します。BLOBデータを一意の名前から遠ざける別のテーブルを作成してみませんか?
CREATE TABLE `data_store_name` SELECT id,uniqname FROM `data_store` WHERE 1=2;
ALTER TABLE `data_store_name` ADD PRIMARY KEY (id);
ALTER TABLE `data_store_name` ADD UNIQUE KEY (uniqname);
ALTER TABLE `data_store_name` ADD INDEX name_id_ndx (uniqname,id);
INSERT INTO `data_store_name` SELECT id,uniqname FROM `data_store`;
これにより、インデックス作成時にBLOBデータの移動が防止されます。
ここからは、常に次のような名前を使用してdata_storeに参加する必要があります。
SELECT
A.uniqname,B.data
FROM
(SELECT * FROM data_store_name WHERE uniqname = 'mydataname') A
LEFT JOIN
data_store B USING (id)
;
これらの変更を行うと、キーキャッシュ、RAMディスク、およびtmpテーブルを処理するというこの混乱全体が回避されます。
試してみる !!!