次のように、値とハッシュのテーブルを考えます。
+------------+----------+------+-----+---------+----------------+
| 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;
クエリの実行中、プロセスリストにステータスSorting result
と表示されます。状況は完全に再現可能です。テーブルに対してINSERT
操作を継続的に実行する別のプロセスがあることに注意してください。
より具体的なクエリは、*
クエリよりも実行に時間がかかるのはなぜですか?パフォーマンス上の理由から、*
クエリは避けるべきだといつも信じていました。
ORDER BY 1
という句は、異なる列を指します。最初はid
、2番目はval
になります。 id
はキーなので、インデックスが付けられ、order by
は簡単な作業になります。ただし、order by val
を実行するには、システムがすべての行を取得し、テーブル全体をval
でソートして、それらの行の1つだけを選択する必要があります。
両方のクエリをorder by id
に変更します。実行時間はほぼ同じになると思います。
クエリのパフォーマンスの違いは、MGによってよく説明されています。私はこれに対処します:
パフォーマンス上の理由から、*クエリは避けるべきだと常に信じてきました。
select *
自体は特にペナルティはありません。誤用すると問題が発生します。単一テーブルのクエリでは、それはうまく機能します。次に、そのテーブルを20列の別のテーブルに結合し、後でそれぞれに多くの列がある5つの他のテーブルに結合を追加します。今それは問題です。理由を説明せずに、バンドエイドで「Xをしない」を教える人もそうです。