EDIT:以下の質問には、観察結果を説明する間違いがありました。私は質問を削除することができますが、これはまだ誰かにとって有用かもしれません。間違いは、サーバー上で実行されている実際のクエリはSELECT * FROM t
(それはばかげていた)だと私は考えていたのだと思っていた。それはSELECT t.* FROM t
だ。 tobyobrianの答えとそのコメントを参照してください。この大きなJOINのスピードアップ
次のように、スキーマを使用する状況ではクエリが低すぎます。テーブルt
は、t_id
によってインデックスされたデータ行を持っています。
CREATE TABLE t (
t_id INT NOT NULL PRIMARY KEY,
data columns...
);
CREATE TABLE t_x (
t_id INT NOT NULL,
x_id INT NOT NULL,
PRIMARY KEY (t_id, x_id),
KEY (x_id)
);
CREATE TABLE t_y (
t_id INT NOT NULL,
y_id INT NOT NULL,
PRIMARY KEY (t_id, y_id),
KEY (y_id)
);
私はどちらかで参照されていないもの、すなわちt
に浮遊行をエクスポートする必要があります:t
は、結合に必要なだけforeignsキーが含まれているそれぞれの接合テーブルt_x
とt_y
を経由して、テーブルx
とy
に隣接しますジャンクションテーブル。
SELECT t.* FROM t
LEFT JOIN t_x ON t_x.t_id=t.t_id
LEFT JOIN t_y ON t_y.t_id=t.t_id
WHERE t_x.t_id IS NULL OR t_y.t_id IS NULL
INTO OUTFILE ...;
t
t_x
とt_y
両方が約25 M行を有するが21 M行を有します。したがって、これは自然にゆっくりとしたクエリになります。
私はMyISAMを使用していますので、t_x
とt_y
のインデックスを事前にロードすることでスピードアップしようと考えていました。 t_x.MYI
とt_y.MYI
の組み合わされたサイズは約1.2Mバイトでしたので、私はそれらの専用キーバッファーを作成し、それらのPRIMARYキーを専用バッファーに割り当て、LOAD INDEX INTOにそれらをキャッシュしました。
しかし、動作中のクエリを見ると、mysqldは約1%のCPUを使用しています。平均システムIOの待ちキュー長は約5であり、mysqldの平均シークサイズは250kの範囲です。さらに、IOのほとんどはt_x.MYI
とt_x.MYD
からmysqldを読み込みます。
私は理解していない:
mysqldがすべてで
.MYD
ファイルを読んでいるのはなぜ?なぜ、mysqldはプリロードされた
t_x
とt_y
インデックスを使用していないのですか?
それは、2つの列の上にあることt_x
とt_y
主キーとは何かを持ってもらえますか?
EDIT:クエリは次のように説明し
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+---------+---------+-----------+----------+-------------+
| 1 | SIMPLE | t | ALL | NULL | NULL | NULL | NULL | 20980052 | |
| 1 | SIMPLE | t_x | ref | PRIMARY | PRIMARY | 4 | db.t.t_id | 235849 | Using index |
| 1 | SIMPLE | t_y | ref | PRIMARY | PRIMARY | 4 | db.t.t_id | 207947 | Using where |
+----+-------------+-------+------+---------------+---------+---------+-----------+----------+-------------+
これはあなたの質問とは正確には関係ありませんが、いずれの表にも記載されていないものが必要だと言います。これは英語のあいまいなステートメントです。0/2テーブルに記載されていないもの、または1/2または0/2テーブルに記載されていないものが必要ですか?あなたのクエリーが後者を選択します – tobyodavies
また、そのクエリーのためのEXPLAINの出力は何ですか? – tobyodavies
'SELECT t。*'ではなく 'SELECT t.t_id'だけでは違いますか?それが速ければ、後でt. *から...を選択できます。どこのt.t_ID IN(t.t_id ...を選択))? – Konerak