假定以下查询已发布到MySQL数据库:
SELECT * FROM table_name;
注意, 没有 ORDER BY给出 任何 子句。
ORDER BY
我的问题是:
MySQL是否能保证结果集行的顺序?
更具体地说,我是否可以假定行将按插入顺序返回?即行插入表的顺序相同。
不,没有保证。除非您使用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行以相反的顺序插入到这些空间中,从末尾向后填充。
因此,行的存储顺序与它们插入的顺序不完全相同。