【问题标题】:Postgres ordering is not consistentPostgres 排序不一致
【发布时间】:2013-08-28 22:12:44
【问题描述】:

我遇到了一个问题,即 postgres 排序结果的排序不一致。我按多个字段排序:ORDER BY categories.position ASC、photos.display_priority

我注意到这一点是因为当您浏览网站时,结果会分页。我发现了一个案例,我从第 1 页转到第 2 页,在第 2 页的顶部,我看到了靠近第 1 页底部的照片。

这是我的第 1 页查询:

SELECT "photos".*
FROM "photos"
    INNER JOIN "categories" ON "categories"."id" = "photos"."category_id"
WHERE "photos"."category_id" IN (221, 633, 377, 216, 634)
    AND (photos.caption IS NOT NULL
        AND photos.category_id IS NOT NULL
        AND photos.rights IS NOT NULL
        AND photos.deleted IS NULL)
ORDER BY categories.position ASC, photos.display_priority DESC
LIMIT 25 OFFSET 0;

还有我的第 2 页查询:

SELECT "photos".*
FROM "photos"
    INNER JOIN "categories" ON "categories"."id" = "photos"."category_id"
WHERE "photos"."category_id" IN (221, 633, 377, 216, 634)
    AND (photos.caption IS NOT NULL
        AND photos.category_id IS NOT NULL
        AND photos.rights IS NOT NULL
        AND photos.deleted IS NULL)
ORDER BY categories.position ASC, photos.display_priority DESC
LIMIT 25 OFFSET 25;

当我尝试同时获取两个页面(偏移量 0,限制 50)并检查两组之间的阈值时,没有重复,这不足为奇。

SELECT "photos".*
FROM "photos"
    INNER JOIN "categories" ON "categories"."id" = "photos"."category_id"
WHERE "photos"."category_id" IN (221, 633, 377, 216, 634)
    AND (photos.caption IS NOT NULL
        AND photos.category_id IS NOT NULL
        AND photos.rights IS NOT NULL
        AND photos.deleted IS NULL)
ORDER BY categories.position ASC, photos.display_priority DESC
LIMIT 50 OFFSET 0;

我的查询有问题吗?是否有我不理解的限制和顺序的操作顺序?

【问题讨论】:

  • 这仍然是可重现的,我们遇到了同样的问题......

标签: postgresql


【解决方案1】:

听起来categories.positionphotos.display_priority 对于所有结果行来说并不是唯一的。当用于排序的值都相等时,数据库服务器不会指定行的顺序;可以按任意顺序返回它们,即使查询之间的表数据没有改变。

要获得一致的排序,您必须添加第三个排序键,保证对所有行都是唯一的,例如该特定行的标识值。

【讨论】:

  • 你是对的。这就是原因。奇怪的。我知道这些结果的顺序是随机的,但我认为它仍然是一致的。我从没想过从一个查询到下一个查询,我只是在更改那些顺序会改变的偏移量。无论如何,谢谢你帮助我!
  • @KeithSchacht 没问题。行重新排序的原因可能是因为基础表发生了变化。有许多因素可能会影响返回的行的顺序。即使在数据集的最后添加一行(排序后),这也会影响其他行的排序方式。其他不改变数据本身而只是重新排列数据的操作(如VACUUM FULLCLUSTER)通常会改变具有相同顺序的行相对于彼此的排列方式。最终,您不能假设相同顺序行的顺序一致。 :)
  • 我知道原则上排序可能会改变。在这种情况下,奇怪的是它是可重现的。对于这个特定的查询,每次我执行第一页 LIMIT 都是一种方式,而每次我执行第二页 LIMIT 时,它都会以不同的方式排序。这中间没有对数据库进行任何更改。我确信这只是一些底层 SQL 引擎优化,但这是我在构建应用程序时要牢记的一个很好的教训。
  • @KeithSchacht 是的,这很可能是由 LIMIT 子句不同引起的。例如,规划器可能会为每个查询生成稍微不同的计划。
猜你喜欢
  • 1970-01-01
  • 2013-07-26
  • 1970-01-01
  • 2022-11-30
  • 2015-09-03
  • 2015-10-05
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
相关资源
最近更新 更多