一尘不染

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

mysql

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

SELECT * FROM table_name;

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

我的问题是:

MySQL是否能保证结果集行的顺序?

更具体地说,我是否可以假定行将按插入顺序返回?即行插入表的顺序相同。


阅读 388

收藏
2020-05-17

共1个答案

一尘不染

不,没有保证。除非您使用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行以相反的顺序插入到这些空间中,从末尾向后填充。

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

2020-05-17