“SELECT * FROM table_name;”的MySQL行顺序

假设以下查询发布到MySQL数据库:

SELECT * FROM table_name; 

请注意,没有给出ORDER BY子句。

我的问题是:

MySQL是否给出了结果集行将被赋予的顺序的保证? 更具体地说,我可以假定行将以插入顺序返回(即将行插入到表中的顺序相同)? 为什么? 为什么不?

假设下面的表结构:

 CREATE TABLE table_name ( foo1 mediumint(8) unsigned NOT NULL default '0', foo2 mediumint(8) unsigned NOT NULL default '0', foo3 mediumint(8) unsigned NOT NULL default '0', foo4 mediumint(8) unsigned NOT NULL default '0', UNIQUE KEY (foo1, foo2) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

不,没有保证。 除非您使用ORDER BY子句指定订单,否则订单完全取决于内部实施细节。 也就是说,对RDBMS引擎来说最方便的是什么。

实际上,这些行可能会以其原始的插入顺序(或者更准确地说,这些行在物理存储中存在的顺序)返回,但是您不应该依赖这个。 如果将应用程序移植到其他品牌的RDBMS,或者即使您升级到可能以不同方式实现存储的较新版本的MySQL,行也可能以其他顺序返回。

后面的观点对于任何符合SQL的RDBMS都适用。


下面是我的意思是存储行中存在的顺序,而不是它们创build的顺序:

 CREATE TABLE foo (id SERIAL PRIMARY KEY, bar CHAR(10)); -- create rows with id 1 through 10 INSERT INTO foo (bar) VALUES ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'); DELETE FROM foo WHERE id BETWEEN 4 AND 7; +----+---------+ | id | bar | +----+---------+ | 1 | testing | | 2 | testing | | 3 | testing | | 8 | testing | | 9 | testing | | 10 | testing | +----+---------+ 

所以现在我们有六排。 此时的存储包含删除中间行后留下的行3和行8之间的间隔。 删除行不会对这些空白进行碎片整理。

 -- create rows with id 11 through 20 INSERT INTO foo (bar) VALUES ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'), ('testing'); SELECT * FROM foo; +----+---------+ | id | bar | +----+---------+ | 1 | testing | | 2 | testing | | 3 | testing | | 14 | testing | | 13 | testing | | 12 | testing | | 11 | testing | | 8 | testing | | 9 | testing | | 10 | testing | | 15 | testing | | 16 | testing | | 17 | testing | | 18 | testing | | 19 | testing | | 20 | testing | +----+---------+ 

请注意,在将新行添加到表尾后,MySQL如何重新使用通过删除行打开的空格。 另外请注意,第11行至第14行以相反顺序插入这些空间,从尾部向后填充。

因此,行存储的顺序并不完全是它们被插入的顺序。

通过此线程 ,默认sorting是MyISAM的插入顺序,InnoDB的主键升序。 但我不认为这是一个保证,只是如何工作。

你不能。

有时MySQL会用你不期望的键来执行select查询。 考虑这个表格:

 CREATE TABLE `user_permissions` ( `permId` int(5) unsigned NOT NULL AUTO_INCREMENT, `permKey` varchar(16) NOT NULL, `permDesc` varchar(64) DEFAULT NULL, PRIMARY KEY (`permId`), KEY `key_lookup` (`permKey`,`permId`,`permDesc`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

MySQL几乎总是使用key_lookup键在这个表上做任何select操作; 因为permKey是第一个字段,所以它通常最终会被这个键“sorting”(按字母顺序显示,但不完全是)。

如果没有ORDER BY子句,MySQL(以及大多数/所有的RDBMS引擎)将尽可能快地获取数据。

从使用MySQL SELECT语句检索数据:SELECT语句

显示的数据不是有序的。 通常,logging是按照插入数据库的相同顺序检索的

是的,根据评论

尽pipelogging通常按照插入到数据库的顺序进行检索,但不能依赖于保留的特定顺序。 如果您的数据库已经备份和恢复,或者对数据库执行了维护操作,那么MySQL可能会改变内部存储logging的顺序。

不,绝对不是。 根据您使用的数据库引擎(ISAM或InnoDB),表结构通常是某种b-树 ,以便更快地search行。 这与插入顺序无关,更多与数据库如何基于主键构build索引(或者在没有键的情况下,如何存储表格堆)有关。

MySQL 5.6中的结果在插入顺序中没有被默认select,你可以执行更新等,它会以任何顺序返回查询