Mysql:indexes 和 table 中的行顺序

Mysql:indexes and order of rows in a table

第 1 步:

我正在创建一个简单的 table。

CREATE TABLE `indexs`.`table_one` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  PRIMARY KEY (`id`));

第 2 步:

我在其中插入了两个 table。

insert into table_one (name) values ("B");
insert into table_one (name) values ("A");

第 3 步:

我做了一个select,我得到一个table,其中的记录是按id排序的

SELECT * FROM table_one;

这是预期的结果,因为在mysql中主键是聚集索引,因此数据将按其物理排序。

现在是我不明白的部分。

第 4 步:

我正在名称列上创建索引。

CREATE INDEX index_name ON table_one(name)

我再次重复第 3 步,但得到了不同的结果。这些行现在根据名称列排序。

为什么会这样?为什么 table 中的行顺序会根据 name 列上的新索引发生变化,因为据我了解,在 mysql 中,主键是唯一的聚集索引,并且所有额外创建的索引是次要的。

I make a select, I get a table, the records in which are ordered by id. [...] This is the expected result, because in mysql the primary key is a clustered index, therefore the data will be physically ordered by it.

这里对一个概念有些误解

Table 行没有固有的顺序:它们代表 无序的 行集。虽然聚簇索引强制对存储中的数据进行物理排序,但它不能保证 select 查询 return 行的顺序。

如果您希望对查询结果进行排序,请使用 order by 子句。如果没有这样的子句,排序或行是 undefined:数据库可以自由地 return 结果以任何它喜欢的顺序,并且不保证结果在连续执行中是一致的相同的查询。

select * from table_one order by id;
select * from table_one order by name;

(专线小巴解释最多)

Why is this happening? why the order of the rows in the table changes in accordance with the new index on the name column

使用 EXPLAIN SELECT ... -- 它可能会提示我要提出的建议。

您添加了 INDEX(name)。在 InnoDB 中,PRIMARY KEY 列被附加到每个二级索引的末尾。所以它实际上是一个按 (name,id) 排序并且只包含这些列的 BTree。

现在,优化器可以自由地从索引中获取数据,因为它具有您要求的所有内容(id 和名称)。 (这个指标叫做“覆盖”。)

由于您没有指定 ORDER BY,结果集排序有效(请参阅 GMB 的讨论)。

故事的寓意: 如果您想要排序,请指定 ORDER BY。 (如果优化器可以在不进行排序的情况下了解如何提供数据,那么它就足够聪明,可以“不做额外的工作”。

进一步实验:向 table 添加另一列,但不要更改索引。现在您会发现 SELECT * FROM t 的排序与 SELECT id, name FROM t 不同。我想我已经给了你足够的线索来预测这种差异,如果没有,请问。