# 使用索引扫描来做排序

MySQL 有两种方式可以生成有序的结果：通过<mark style="color:blue;">**排序**</mark>操作，或者<mark style="color:blue;">**按索引顺序扫描**</mark>。**如果在 EXPLAIN 的输出结果中，type 列的值为 “index”，则说明 MySQL 使用了索引扫描来做排序。**

> 扫描索引本身是很快的，因为只需要从一条索引记录移动到紧接着的下一条记录。但**如果索引不能覆盖查询所需的全部列，那么就不得不每扫描一条索引记录都回表查询一次对应的记录**。这基本上都是**随机 I/O**，因此<mark style="color:orange;">**按索引顺序读取数据的速度通常要比顺序地全表扫描慢，尤其是在 I/O 密集型的应用负载上**</mark>。

<mark style="color:blue;">**MySQL 可以使用同一个索引既满足排序，又用于查找行。**</mark>因此，如果可能，设计索引时应该尽可能地同时满足这两项任务，这样是最好的。

* 只有**当索引的顺序和 ORDER BY 子句的顺序完全一致**，并且**所有列的排序方向（倒序或正序）都一样**时，MySQL 才能使用索引来对结果做排序。
* 如果查询需要**联接多张表**，则只有当 **ORDER BY 子句引用的字段全部在第一个表中**时，才能使用索引做排序。
* ORDER BY 子句和查找型查询的限制是一样的：需要满足索引的**最左前缀**的要求，否则，MySQL 需要执行排序操作，而无法利用索引排序。

  有一种特殊情况，如果**前导列为常量**的时候，ORDER BY 子句中的列也可以不满足索引的最左前缀的要求。如果在 WHERE 子句或者 JOIN 子句中将这些列指定为了常量，就可以“填补”索引字段的间隙了。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bohans.gitbook.io/ji-chu/mysql/sql-you-hua/suo-yin/shi-yong-suo-yin-sao-miao-lai-zuo-pai-xu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
