什么是“SELECT * FROM table_name;”的MySQL行顺序?

时间:2009-12-22 22:32:14

标签: mysql select sql-order-by

假设向MySQL数据库发出以下查询:

SELECT * FROM table_name;

请注意,没有 ORDER BY条款。

我的问题是:

MySQL是否对结果集行的顺序给出任何保证?

更具体地说,我可以假设行将按插入顺序返回吗?这与行插入表中的顺序相同。

6 个答案:

答案 0 :(得分:27)

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

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

对于任何符合SQL的RDBMS,后一点都适用。


以下是存储中行存在顺序与存储顺序的比较:

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以相反的顺序插入这些空间,从末端向后填充。

因此,存储行的顺序与插入行的顺序不完全相同。

答案 1 :(得分:5)

Per this thread,默认排序是MyISAM的插入顺序,InnoDB的主键升序。但我不认为这是一种保证,只是它的工作原理。

答案 2 :(得分:4)

不,你不能。

有时,MySQL会使用您不期望的键执行选择查询。考虑一下这个表:

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键对该表执行任何选择操作;由于permKey是第一个字段,因此它通常会被此键“排序”(按字母顺序排列,但不完全相同)。

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

答案 3 :(得分:2)

来自Retrieving Data Using the MySQL SELECT Statement : The SELECT Statement

  

显示的数据未订购。   通常在中检索记录   它们的插入顺序相同   进入数据库

是的,根据评论

  

虽然记录正常   按照他们的顺序检索   你插入到数据库中   不能依赖特定的订单   被保存。如果您的数据库是   备份和恢复,或者如果是   执行维护操作   数据库,MySQL可能会改变   存储记录的顺序   内部。

答案 4 :(得分:1)

不,绝对不是。根据您正在使用的数据库引擎(ISAM或InnoDB),表结构将generally be some kind of b-tree以允许更快地搜索行。这与插入顺序无关,更多的是与数据库如何基于主键构建索引(或者在没有键的情况下,如何存储表堆)。

答案 5 :(得分:0)

默认情况下,在插入顺序中没有选择mysql 5.6中的结果,你可以进行更新等,并按任何顺序重新启动查询