mysql:indexes and 表中行的顺序

kyks70gy  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(269)

第一步:
我正在创建一个简单的表。

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

第二步:
我在这张table上插了两块。

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

第三步:
我做一个select,得到一个表,其中的记录是按id排序的。

SELECT * FROM table_one;


这是预期的结果,因为在mysql中主键是聚集索引,因此数据将按它进行物理排序。
现在我不明白的部分。
第四步:
我正在名称列上创建索引。

CREATE INDEX index_name ON table_one(name)

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

为什么会这样?为什么表中的行的顺序会随着name列上的新索引而改变,因为据我所知,在mysql中,主键是唯一的聚集索引,另外创建的所有索引都是辅助索引。

mwyxok5s

mwyxok5s1#

我做了一个select,得到一个表,其中的记录是按id排序的[…]这是预期的结果,因为在mysql中主键是一个聚集索引,因此数据将按它进行物理排序。
这里对一个概念有些误解。
表行没有固有的顺序:它们表示无序的行集。虽然聚集索引强制对存储中的数据进行物理排序,但它不能保证数据返回行的顺序 select 查询。
如果希望对查询结果进行排序,则使用 order by 条款。如果没有这样的子句,则顺序或行是未定义的:数据库可以随意按其喜欢的顺序返回结果,并且不能保证在连续执行同一查询时结果是一致的。

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

r6vfmomb2#

(gmb解释最多)
为什么会这样?为什么表中的行的顺序会随着名称列上的新索引而改变
使用 EXPLAIN SELECT ... --它可能会给我的建议提供一个线索。
你补充道 INDEX(name) . 在innodb中 PRIMARY KEY 列固定在每个次索引的末尾。所以它实际上是由 (name,id) 只包含那些列。
现在,优化器可以自由地从索引中获取数据,因为它拥有您所要求的一切(id和name)(此索引称为“覆盖”。)
因为您没有指定 ORDER BY ,结果集排序是有效的(参见gmb的讨论)。
这个故事的寓意是:如果你想订购,请详细说明 ORDER BY . (如果优化器能够看到如何在不进行排序的情况下提供数据,那么它就足够聪明,可以“不做额外的工作”。
进一步的实验:向表中添加另一列,但不更改索引。现在你会发现 SELECT * FROM t 顺序不同于 SELECT id, name FROM t . 我想我已经给了你足够的线索来预测这种差异,如果没有,问吧。

相关问题