2016-07-07 5 views
2

SELECT * FROM Table VSのパフォーマンスペナルティSELECT * FROM (SELECT * FROM Table AS A) AS Bパフォーマンスペナルティが

は何私の質問があるの照会しますWHERE句が指定されていないため)、WHERE句はWHERE句が指定されていないので、WHERE句はWHERE句を使用しないため、2回繰り返す必要があります。ありがとう...

答えて

2

この質問に対する答えは、5.7または5.7より前にmysqlを使用しているかどうかによって決まります。私はあなたの質問を少し変えているかもしれませんが、うまくいけば、あなたが後にしていることを以下のように捕捉してください。

SELECT * FROM Tableは、クラスタ化インデックス(物理的な順序付け)を介してテーブルスキャンを実行します。主キーがない場合は、implicitlyがエンジンで使用可能です。あなたが言うようにwhere節はありません。他の索引のフィルタリングまたは選択は試行されません。

出力(alsoを参照)は、その要約に1行を示します。Explain出力これは比較的単純です。派生テーブルBによる説明出力とパフォーマンスは、5.7より前のバージョンか5.7より前のバージョンかによって異なります。

ドキュメントDerived Tables in MySQL 5.7は、外部クエリに組み込まれているマテリアライズド・テーブル出力が変更されたため、後者ではペナルティが発生しません。以前のバージョンでは、派生した一時テーブルを使用してかなりのオーバーヘッドが発生しました。

5.7より前のパフォーマンスペナルティをテストするのは簡単です。あなたの質問の派生テーブルがパフォーマンスに影響を与えているという顕著な影響を見るためには、中程度のサイズのテーブルが必要です。次の例は、バージョン5.6に小さなテーブルの上にある:

explain 
select qm1.title 
from questions_mysql qm1 
join questions_mysql qm2 
on qm2.qid<qm1.qid 
where qm1.qid>3333 and qm1.status='O'; 
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra           | 
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+ 
| 1 | SIMPLE  | qm1 | range | PRIMARY,cactus1 | PRIMARY | 4  | NULL | 5441 | Using where         | 
| 1 | SIMPLE  | qm2 | ALL | PRIMARY,cactus1 | NULL | NULL | NULL | 10882 | Range checked for each record (index map: 0x3) | 
+----+-------------+-------+-------+-----------------+---------+---------+------+-------+------------------------------------------------+ 


explain 
select b.title from 
( select qid,title from questions_mysql where qid>3333 and status='O' 
) b 
join questions_mysql qm2 
on qm2.qid<b.qid; 
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+ 
| id | select_type | table   | type | possible_keys | key  | key_len | ref | rows | Extra            | 
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+ 
| 1 | PRIMARY  | qm2    | index | PRIMARY,cactus1 | cactus1 | 10  | NULL | 10882 | Using index          | 
| 1 | PRIMARY  | <derived2>  | ALL | NULL   | NULL | NULL | NULL | 5441 | Using where; Using join buffer (Block Nested Loop) | 
| 2 | DERIVED  | questions_mysql | range | PRIMARY,cactus1 | PRIMARY | 4  | NULL | 5441 | Using where          | 
+----+-------------+-----------------+-------+-----------------+---------+---------+------+-------+----------------------------------------------------+ 

注、私は質問を変更しましたが、それは表の派生影響を示し、オプティマイザでインデックスの使用の欠如は、前5.7へのバージョンにあり。派生テーブルは、索引がマテリアライズされているときに索引を利用します。しかしその後、一時的なテーブルとしてオーバーヘッドを費やし、インデックスを使用せずに外部クエリに組み込みます。これはバージョン5.7のケースではありません

+0

説明: –

+0

パフォーマンスの問題について、2つのサブクエリ間の結合操作では、外部クエリではなく内部クエリでLIMIT句を指定することをお勧めしますか? '((SELECT id FROM Table1)NATURAL JOIN表2))LIMIT 10'(これはいくつかの構文エラーを含んでいる可能性があります。テーブル命名との関係ですが...)?ありがとう:) –

+0

あなたのサーバーのバージョン、あなたのスキーマでそれを再生することをお勧めします。以下は、サーバー以外のラップトップ上の[5.6](http://i.imgur.com/jxsrvB2.jpg)です。自然な結合は使用しません。私は幅広い筆のストロークの回答をしないようにします。特に、同じように見えるかもしれない 'Explain'の出力に。それはスタック上であまりにも多く発生します。代わりに、より大きなデータセットでクエリを指し示し、最悪の実行クエリや[ここ](http://stackoverflow.com/a/38189113)などの一般的な調査で少なくとも15分のテストを実行します。パフォーマンスはオプティマイザに基づいてバージョンによって異なります。 – Drew

関連する問題