我想到这个问题是从观察mysql的自然排序状态引发的,我们用的很多mysql管理软件,在列出表数据时一般都用的以下代码
SELECT * FROM table_name LIMIT x OFFSET y
这个时候没有指定任何排序字段,那么在mysql内部就应该有一个类似oracle或者pgsql里面sequence id的东西,做为它的默认索引来实现排序之类的东西。但我从来没看到有人提过mysql有这个玩意。
另一个佐证是如果你指定了一个自增id作为主键,在我们预想中如果执行上面的语句,主键的排序顺序应该一致,实际上并不是这样,虽然大部分是一致的,但是有少部分会打乱。因此他一定有一个内部的排序机制,这个机制是什么?
单说MyISAM吧。 MyISAM的数据和索引是分开的,当你执行一个简单的select *的时候,按照的就是数据在磁盘上的排列顺序(你可以把这个顺序理解为sequenceid)。 但是必须指出的是,数据空间是会复用的,也就是说当你在插入一行数据的时候,如果前面被删除的区块有合适空位,就会放到这空位中。 因此select *并不保证是按照插入顺序。 不知道这么说有木有清楚。。。
select * from tb limit oo offset xx; 这种查询是不走索引的,也就是说根本就不排序,结果的顺序是你写入数据的顺序。
mysql索引是这样的。myisam各种没底线,没限制,每一个索引叶子节点存索引列值,指向数据在磁盘的地址。innodb,要求每张表有一个聚簇索引,这东西默认是Primary Key,没有的话就是第一个unique key,再没有就自己创建一个autoincrement。这个聚簇索引排成一棵B树,每个叶子是局促的那个字段值,指向整行数据。其他的索引都叫二级索引,存的是索引列值,指向聚簇索引的列值。这些索引单独存储,所以不知名道姓的说用他们,他们是不会出来的,尤其是select * 这种操作,反正是要去取出所有的数据的,而且没要求排序,那么再走一次PK排序,会慢,所以就直接顺序读出来了。
---- 补充 ----
MyISAM的存储顺序就是写入顺序,他是顺着一个一个的写下去的,所以MyISAM查出来的,完全按照写入顺序。innodb的存储分页的,每一个page里的数据是按照聚簇索引排序的,但是page之间是无序的,所以会发现,在数据量比较小的时候,会发现查出来的数据其实还是按照聚簇索引的asc排序的,但是数据多了就会出现部分数据混乱,就是因为page之间的顺序是乱的。