可疑的SQL实践 - 按ID而不是创建时间排序

时间:2012-12-22 18:59:15

标签: mysql sql database query-optimization

所以我有一个有趣的问题,我不确定是否被视为'黑客'。我查看了一些问题,但没有找到重复,所以在这里。基本上,我需要知道这是不可靠还是被认为是不好的做法。

我有一个非常简单的表,其中包含唯一的自动递增ID和created_at时间戳。  (我的问题的简化版本,以澄清有问题的概念)

+-----------+--------------------+
| id        |created_at          |
+-----------+--------------------+
| 1         |2012-12-11 20:35:19 |
| 2         |2012-12-12 20:35:19 |
| 3         |2012-12-13 20:35:19 |
| 4         |2012-12-14 20:35:19 |
+-----------+--------------------+

这两个列都是动态添加的,因此可以说新的“插入”将始终具有更高的ID,而总是具有更长的日期。

目标 - 非常简单地按降序获取created_at排序的结果

SOLUTION ONE - 按日期降序排序的查询

SELECT * FROM tablename
ORDER BY created_at DESC

解决方案二 - 按ID按降序排序的查询

SELECT * FROM tablename
ORDER BY id DESC

解决方案二被视为不良做法吗?或解决方案二是正确的做事方式。任何对你的推理的解释都会非常有用,因为我试图理解这个概念,而不仅仅是简单地得到答案。提前谢谢。

5 个答案:

答案 0 :(得分:7)

在典型的练习中,您几乎总是可以假设可以对自动增量ID进行排序,以便按创建顺序(任一方向)提供记录。但是,您应该注意,根据您的数据,这不被认为是可移植的。您可以将数据移动到重新创建密钥的另一个系统,但created_at数据是相同的。

这个问题确实很StackOverflow discussion

基本摘要是第一个解决方案,按created_at排序,被认为是最佳实践。但是,请确保正确索引created_at字段以提供最佳性能。

答案 1 :(得分:6)

除了唯一标识行的内容之外,您不应该依赖ID。这是一个任意数字,恰好与创建记录的顺序相对应。

说你有这张桌子

ID  creation_date
1   2010-10-25
2   2010-10-26
3   2012-03-05

在这种情况下,对ID而不是creation_date进行排序可以正常工作。

现在将来你会意识到,哦,哎呀,你必须将记录ID#2的创建日期改为2010-09-17。您现在使用ID排序会以相同的顺序报告记录:

1   2010-10-25
2   2010-09-17
3   2012-03-05

即使新日期应该是:

2   2010-09-17
1   2010-10-25
3   2012-03-05

简短版本:将数据列用于创建它们的目的。不要依赖数据的副作用。

答案 2 :(得分:4)

这两个选项之间存在一些差异。


首先,他们可以给出不同的结果。

created_at的值可能会受到服务器上调整时间的影响,但id列不受影响。如果向后调整时间(手动或通过时间同步软件自动调整),您可以获得稍后插入的记录,但时间戳记在之前插入的记录之前。在这种情况下,您将获得不同的订单,具体取决于您订购的列。您认为哪种订单“正确”取决于您。


第二是表现。 clustered index ORDER BY可能会更快id

  

群集索引如何加速查询

     

通过聚簇索引访问行很快,因为行数据位于索引搜索所在的同一页面上。

默认情况下,群集密钥是主键,在您的情况下可能是ORDER BY id列。您可能会发现ORDER BY created_at略快于{{1}}。

答案 3 :(得分:3)

主键,尤其是代理类型的主键,除了它们仅仅是允许唯一可识别记录的事实之外,通常不代表任何类型的有意义的数据。由于这种情况下的日期确实代表了在其主要功能之外有意义的有意义的数据,我会说根据日期排序是一种更合理的方法。

答案 4 :(得分:3)

插入顺序按ID订单排序。

如果您有可以延迟插入的用例,例如批处理,那么您必须按created_at命令按时间排序。

如果满足您的需要,两者都可以接受。