SELECT *がSELECT fooよりもはるかに高速なのはなぜですか?


28

次のような値とハッシュの表を考えてみましょう。

+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| val        | char(9)  | NO   |     | NULL    |                |
| val_hashed | char(50) | YES  |     | NULL    |                |
+------------+----------+------+-----+---------+----------------+

次のクエリは0.00秒で終了します。

SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;

ただし、このクエリには3分17秒かかります。

SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;

クエリの実行中にプロセスリストがstatusとして表示されることがわかりますSorting result。状況は完全に再現可能です。INSERTテーブルで操作を継続的に実行する別のプロセスがあることに注意してください。

クエリよりも具体的なクエリの実行に時間がかかるのはなぜ*ですか?*パフォーマンス上の理由から、クエリは避けるべきだと常に考えてきました。


7
最初のステートメントは、おそらく主キーインデックスon idを使用して最初の行を見つけます。2番目の方法では、(インデックス化されていない)val列で完全な結果をソートする必要があります。
a_horse_with_no_name 14

8
ORDER BY NUMBER構文は非常にエラーが発生しやすくなります。
usr 14

2
最後のコメントにSELECT *列インデックスを追加すると、ORDER BYどの列がソートされているかわかりにくくなります。これは、*s ...
lc

@lc。、どういう意味ですか?
Pacerier

@Pacerier *は明示的ではないということです。「第三のいずれかでソート私のすべての列を与えると」言っては、「スーパーマーケットに行くとあなたが渡されたどのように多くのトラフィックライトを教えて」と言っとして決定論などについてです
LCを。

回答:


33

フレーズORDER BY 1は異なる列を指します。最初にはid、2番目になりvalます。idキーであるため、インデックスが作成されorder by、些細な作業になります。order by valしかし、システムはすべての行によるソート完全なテーブルを取得する必要がありますvalし、それらの行のひとつを選択し、。

両方のクエリを変更するorder by idと、実行時間はほぼ同じになると思います。


3
時々、最も難しい質問は、ただ顔を凝視している質問です。マイケル、ありがとう!
dotancohen

7

クエリのパフォーマンスの違いは、MGによって十分に説明されています。これに対処します。

私は常に、パフォーマンス上の理由からクエリを避けるべきだと常に信じてきました。

select *それ自体に特定の罰則はありません。誤用されると問題が生じます。単一テーブルのクエリでは、問題なく機能します。そのテーブルを20列の別のテーブルに結合し、後でそれぞれに多くの列を持つ5つの他のテーブルに結合を追加します。今、それは問題です。そのため、理由を説明せずに、幅広いバンドエイド「決してXをやる」を教える人々も同様です。


3
SELECT *単一テーブルのクエリでも問題になる可能性があります。たとえば、SELECT * FROM hashes ORDER BY val;おそらくテーブル全体のスキャンを実行し、次にwhile SELECT val FROM hashes ORDER BY val;を実行するとインデックス全体のスキャンのみが実行され、ソートは実行されません(valにインデックスが存在すると仮定)。そのため、必要な結果のみを選択しても問題はありません。
ypercubeᵀᴹ


@ ypercube、sub -select select(*)としてのみ使用されている場合でも発生しますか?組み込みの選択であるため、MySQLは選択が必要な実際の列を把握するのに十分スマートではありませんか?
Pacerier

@Pacerier mysqlオプティマイザーには、使用しているバージョンに応じて異なる「スマートネス」レベルがあります。gernealでは、ネストされたサブクエリに関してかなり愚かだったので、彼を助けることができるものは何でも、それは良かったです。
ypercubeᵀᴹ

@ypercube、ああ、それはpgsqlと同じくらいスマートだからです。
Pacerier
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.