什么是"默认顺序由"对于省略Order by子句的mysql Innodb查询?

时间:2018-04-13 11:14:02

标签: mysql sql-order-by innodb

所以我理解并发现帖子表明,当您从DBMS检索数据时,不建议在SQL查询中省略order by子句。

资源&发布咨询(将更新):

SQL Server UNION - What is the default ORDER BY Behaviour

When no 'Order by' is specified, what order does a query choose for your record set?

https://dba.stackexchange.com/questions/6051/what-is-the-default-order-of-records-for-a-select-statement-in-mysql

问题:

如果您想了解更多信息,请参阅下面问题的逻辑。

我的问题是:在带有innoDB引擎的mysql下,是否有人知道DBMS如何有效地为我们提供结果?

我读到这是依赖于实现的,好的,但是有没有办法知道我目前的实现呢?

这究竟在哪里定义?

是来自MySQL,InnoDB,OS-Dependent吗?

那里有什么样的清单吗?

最重要的是,如果我省略order by子句并得到我的结果,我无法确定此代码是否仍适用于较新的数据库版本,并且DBMS永远不会给我相同的结果,我可以吗?

用例&逻辑:

我目前正在编写一个CRUD API,我的数据库中有一个表格,它不包含" id"字段(虽然有PK),所以当我没有任何研究标准显示该表的结果时,我真的不知道我应该用什么来订购结果。我的意思是,我可以使用PK或任何永远不为空的字段,但它不会使它相关。所以我想知道,因为我的CRUD应该适用于任何表格而且我不想通过为这个特定的表添加例外来解决这个问题,我也可以简单地省略order by子句。

最后注意事项:

在我阅读其他帖子,示例和代码示例时,我觉得我想走得太远。我知道,众所周知,在请求中省略Order By子句并且没有可靠的默认订单子句是一种不好的做法,并不是说除非您指定它,否则根本没有订单。

我只是想知道这个定义的位置,并希望了解其内部工作方式或至少在其定义的位置(DBMS /存储引擎/操作系统相关/其他/多个标准) )。我认为这也有利于其他人了解它,并了解这里的内部机制。

感谢您抽出时间阅读!祝你有愉快的一天。

2 个答案:

答案 0 :(得分:0)

如果没有明确的ORDER BY,当前版本的InnoDB将按照其读取的索引的顺序返回行。哪个索引有所不同,但它总是从某个索引中读取。即使从“表”中读取也是一个索引 - 它是主键索引。

如上面的评论所述,我们无法保证在下一版本的InnoDB中保持不变。你应该将它视为一种巧合的行为,它没有记录,MySQL的制造商也不承诺不改变它。

即使它们的实现没有改变,按索引顺序读取也会导致一些您可能不会想到的奇怪效果,并且不会为您提供对您有意义的查询结果集。

例如,默认索引是聚簇索引PRIMARY。这意味着索引顺序与主键中值的顺序相同(而不是插入它们的顺序)。

mysql> create table mytable ( id int primary key, name varchar(20));

mysql> insert into mytable values (3, 'Hermione'), (2, 'Ron'), (1, 'Harry');

mysql> select * from mytable;
+----+----------+
| id | name     |
+----+----------+
|  1 | Harry    |
|  2 | Ron      |
|  3 | Hermione |
+----+----------+

但是如果你的查询使用另一个索引来读取表,就像你只访问二级索引的列一样,你将按顺序获得行:

mysql> alter table mytable add key (name);

mysql> select name from mytable;
+----------+
| name     |
+----------+
| Harry    |
| Hermione |
| Ron      |
+----------+

这表明它正在使用name上的二级索引的索引扫描来读取表:

mysql> explain select name from mytable;
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | mytable | index | NULL          | name | 83      | NULL |    3 | Using index |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+

在更复杂的查询中,预测InnoDB将用于给定查询的索引变得非常棘手。随着数据的变化,这种选择甚至可能每天都在变化。

所有这一切都表明:如果您关心查询结果集的顺序,则应该使用ORDER BY

答案 1 :(得分:0)

比尔的答案很好。但不完整。

  • 如果查询是UNION,它(我认为)将首先传递第一个SELECT的结果(根据规则),然后传递第二个结果。此外,如果表格为PARTITIONed,则可能会执行类似的操作。

  • GROUP BY 可能按分组表达式进行排序,从而产生可预测的顺序,它可能会使用散列技术,这会扰乱行。我不知道如何预测哪个。

  • 用于的派生表是一个有序列表,它传播到父查询的排序中。但最近,ORDER BY被丢弃在该子查询中! (除非有LIMIT。)

底线:如果您关心订单,请添加ORDER BY,即使根据此Q& A

相比之下,MyISAM从这个前提开始:默认顺序是.MYD文件中的顺序。但是DELETEs留下了空白,UPDATEs混淆了空白,而INSERTs更喜欢在附加到文件时填补空白。因此,行顺序是不可预测的。 ALTER TABLE x ORDER BY y暂时设置.MYD订单;这个'功能'不适用于InnoDB。