第一步:
我正在创建一个简单的表。
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中,主键是唯一的聚集索引,另外创建的所有索引都是辅助索引。
2条答案
按热度按时间mwyxok5s1#
我做了一个select,得到一个表,其中的记录是按id排序的[…]这是预期的结果,因为在mysql中主键是一个聚集索引,因此数据将按它进行物理排序。
这里对一个概念有些误解。
表行没有固有的顺序:它们表示无序的行集。虽然聚集索引强制对存储中的数据进行物理排序,但它不能保证数据返回行的顺序
select
查询。如果希望对查询结果进行排序,则使用
order by
条款。如果没有这样的子句,则顺序或行是未定义的:数据库可以随意按其喜欢的顺序返回结果,并且不能保证在连续执行同一查询时结果是一致的。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
. 我想我已经给了你足够的线索来预测这种差异,如果没有,问吧。