我读过很多SQL代码,似乎开发人员认为默认的排序顺序始终存在。例如,在构建HTML选择列表时,他们只需SELECT id, name FROM table
而不会发出ORDER BY
子句。
根据我自己的经验,如果没有给出ORDER BY
子句且没有索引,dbms总是使用FIFO命令数据。但是,订单无法保证。但是,如果没有对表进行任何更改,我从未见过dbms重新排序数据。
如果表格没有变化,您是否曾经历过以非确定性顺序选择数据的dbms?
始终放置ORDER BY子句是最佳做法吗?
答案 0 :(得分:47)
没有默认的排序顺序。即使表具有聚簇索引,也不能保证按该顺序获得结果。如果您需要特定订单,则必须使用order by子句。
答案 1 :(得分:17)
正如其他海报所提到的,如果你没有指定一个排序顺序,那么SQL标准会说结果可以是查询处理器最方便和最有效的顺序。
假设您为CUSTOMER表的所有行执行简单的无序SELECT,该表没有索引且没有主键。很可能,甚至可能,查询处理器将执行直接表扫描并按照它们最初插入的顺序生成行(为您提供所见的FIFO行为)。
如果您在STATE和CITY字段上添加索引(按此顺序),然后查询WHERE STATE = 'NY'
,查询处理器可能会认为扫描STATE ='NY'的索引条目更有效而不是做全表扫描。在这种情况下,它可能会以STATE,CITY顺序实现行。
即便如此也不确定。例如,如果查询处理器收集的统计信息显示表中几乎所有STATE值都是“NY”(可能是因为数据库是基于Albany的设备租赁业务),它可能会认为表扫描实际上更便宜而不是索引扫描,你会再次看到FIFO。
了解有关数据库如何规划查询的基础知识是个好主意。您可以使用EXPLAIN
语句查看DBMS如何执行任何给定查询,然后使用它来优化查询,在某些情况下可以使用数量级。这是一个值得学习的有趣和有用的领域。
答案 2 :(得分:9)
如果您希望数据一致排序,是的 - 您必须使用ORDER BY
。
答案 3 :(得分:6)
是。没有ORDER BY的“默认订单”,并且无法保证您将数据以FIFO / LIFO或任何其他顺序返回。
对于使用“SELECT id,name FROM table”的开发人员来说,他们要么不合适,要么他们不关心任何出现的顺序。
答案 4 :(得分:3)
没有严重的RDBMS保证任何订单,除非指定显式的ORDER BY。
其他任何东西都只是纯粹的运气或无形的 - 如果你想要订单,你必须指定ORDER BY - 没有办法解决这个问题。
答案 5 :(得分:3)
如果您想要订购数据,保证任何事情的唯一方法(我知道的每个主要RDBMS系统,绝对是Sql Server和Oracle)都要包含一个ORDER BY子句。 FIFO与没有ORDER BY子句的订单数据完全无关,并且没有任何DEFAULT排序顺序的概念。所谓的DEFAULT排序顺序基本上是引擎获取数据,这可能是基于索引,缓存数据,同时执行查询,服务器上的负载等等的任何顺序。
This other stackoverflow thread基本上涵盖了与Sql Server相同的概念,AlexK blogged a repo来演示行为。
答案 6 :(得分:3)
即使像SELECT ... FROM table
这样的简单查询也可以按各种顺序返回数据。我知道这在理论上是正确的,我知道这在实践中是正确的,并且我已经看到了很多情况,当顺序在后续执行之间发生变化时,即使表中没有数据发生变化也是如此。
执行之间订单更改的典型示例是使用并行计划执行查询时。由于并行运算符在底层线程生成数据时返回数据,因此结果中行的顺序在每次运行之间变化。这种情况使得即使是示例中的简单SELECT也会在每次运行时返回截然不同的结果。
答案 7 :(得分:3)
根据我的SQL经验,大多数时候我没有在SQL中指定 ORDER BY ,因为记录集显示在“ 客户端 “支持动态排序的网格类型控件等 - 在这种情况下,SQL排序不必要,因为无论如何都会检查客户端。
这也是客户端完成的,因为可能会使用相同的查询以不同的顺序在不同的位置显示数据。
因此,最佳做法是在
时输入ORDER BY即。如果前端开发人员无论如何都要“重新排序”它,那就没有意义了,因为它不可能节省整个处理时间。
答案 8 :(得分:1)
您正在阅读的那些SQL查询的编写者可能并不关心返回的数据的顺序。最佳做法是在需要确保返回结果顺序的地方使用它!
答案 9 :(得分:0)
如果有人愿意像我一样使用此功能,我会写这个。
好吧,我得到了令人满意的默认排序顺序,让我们说对于日志表,对索引进行排序。例如,我通常对最后一行日志表(LIFO)感兴趣,所以我将DateTime DESC作为订单。我也试着在主键旁边的其他字段(整数)上添加索引,并且它有效。
CREATE TABLE [dbo].[tableA]([DateTime] [datetime] NOT NULL,
CONSTRAINT [PK_tableA]
PRIMARY KEY CLUSTERED ([DateTime] DESC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
或者在SSMS ......