为什么 SELECT * 会比 SELECT foo 快几个数量级?

dot*_*hen 29 mysql performance select

考虑一个值和哈希表,如下所示:

+------------+----------+------+-----+---------+----------------+
| 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    |                |
+------------+----------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)

以下查询在 0.00 秒内完成:

SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

但是,此查询需要 3 分 17 秒:

SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

我看到当查询运行时,进程列表将其显示为 status Sorting result。这种情况是完全可以重现的。请注意,还有另一个进程INSERT在不断地对表执行操作。

为什么更具体的查询需要比查询更长的时间来运行*我一直认为*应该避免查询,特别是出于性能原因。

Mic*_*een 34

该短语ORDER BY 1指的是不同的列;在第一个它将是id,在第二个val。由于id是键,它将被索引并且order by将是微不足道的工作量。要order by val,但是,系统将检索每一行,排序完整的表按val,然后选择只是那些行之一。

将两个查询更改为order by id,我认为您的执行时间几乎相同。

  • 有时,最棘手的问题是那些直视我们的问题。谢谢,迈克尔! (3认同)

小智 7

MG 很好地解释了查询中的性能差异。我要解决这个问题:

我一直认为,出于性能原因,应该避免使用 * 查询。

select *本身没有特别的惩罚,滥用时会出现问题。在单表查询中它工作得很好。现在将该表连接到另一个有 20 列的表,然后将连接添加到其他 5 个表,每个表都有很多列。现在这是一个问题。那些在没有解释原因的情况下教授广泛的创可贴“从不做 X”的人也是如此。

  • 即使对于单表查询,`SELECT *` 也可能是一个问题。例如,`SELECT * FROM hashes ORDER BY val;` 可能会进行全表扫描,然后进行排序,而`SELECT val FROM hashes ORDER BY val;` 只会进行全索引扫描,而不进行排序(假设有一个索引存在于 val)。因此,只选择我们需要的结果永远不会有什么坏处。 (5认同)