web-dev-qa-db-ja.com

mysqlセットアップを最適化してインデックスをより速く作成するにはどうすればよいですか?

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テーブルのコピーを妨げる可能性があることを他の場所で読みました(数時間しか節約できない可能性がありますか?)

  • この「並べ替えによる修復」が必要ですか?

3
Dolan Antenucci

まず、バッファサイズにはまだ触れません。あなたが質問で持っているサイズは、途方もなく大きすぎます。

次に、別の所見を示します。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テーブルを処理するというこの混乱全体が回避されます。

試してみる !!!

6
RolandoMySQLDBA