处理默认排序顺序的SQL最佳实践

时间:2009-11-24 21:47:26

标签: sql database sql-order-by

我读过很多SQL代码,似乎开发人员认为默认的排序顺序始终存在。例如,在构建HTML选择列表时,他们只需SELECT id, name FROM table而不会发出ORDER BY子句。

根据我自己的经验,如果没有给出ORDER BY子句且没有索引,dbms总是使用FIFO命令数据。但是,订单无法保证。但是,如果没有对表进行任何更改,我从未见过dbms重新排序数据。

如果表格没有变化,您是否曾经历过以非确定性顺序选择数据的dbms?

始终放置ORDER BY子句是最佳做法吗?

10 个答案:

答案 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
  • 数据的顺序 IS 很重要;和
  • 在数据库级别排序更有效。

即。如果前端开发人员无论如何都要“重新排序”它,那就没有意义了,因为它不可能节省整个处理时间。

答案 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 ......

enter image description here