PostgreSQL 不确定的结果排序

Rya*_*igg 3 postgresql

当我有这个查询时:

SELECT DISTINCT "spree_products".id FROM "spree_products"
INNER JOIN "spree_variants"
   ON "spree_variants"."product_id" = "spree_products"."id"
  AND "spree_variants"."is_master" = 't'
INNER JOIN "spree_prices"
   ON "spree_prices"."variant_id" = "spree_variants"."id"
INNER JOIN "spree_products_taxons"
   ON "spree_products_taxons"."product_id" = "spree_products"."id" 
INNER JOIN "spree_taxons"
   ON "spree_taxons"."id" = "spree_products_taxons"."taxon_id"
WHERE "spree_taxons"."id" IN (13)
AND "spree_prices"."currency" = 'USD'
AND ("spree_products".deleted_at IS NULL
  or "spree_products".deleted_at >= '2013-08-30 06:23:45.881488')
AND ("spree_products".available_on <= '2013-08-30 06:23:45.881974')
AND (spree_prices.amount IS NOT NULL) LIMIT 12 OFFSET 36
Run Code Online (Sandbox Code Playgroud)

我得到一些以不同偏移量返回的记录。例如,我ID=53OFFSET 24和中都看到了一条记录OFFSET 36

如果我ORDER BY spree_products.id在此语句中添加一个子句,它会使顺序确定,并且我永远不会看到以不同偏移量返回的相同记录。

Cra*_*ger 9

这是因为 SQL 标准不要求 PostgreSQL 在没有ORDER BY子句的情况下以任何特定顺序返回行。它可以返回它们,但是感觉如何。参见手册SELECT。特别是:

如果未给出 ORDER BY,则以系统发现最快生成的任何顺序返回行。

使用 LIMIT 时,最好使用 ORDER BY 子句将结果行限制为唯一顺序。否则,您将获得查询行的不可预测的子集——您可能会要求从第十行到第二十行,但从第十行到第二十行的顺序是什么?除非您指定 ORDER BY,否则您不知道什么顺序。

在几乎所有情况下,这都会造成LIMIT和/或OFFSET没有ORDER BY不安全。如果您在内部查询中强制排序,这是允许的,这是一种性能技巧,但这很少是一个好主意。

您必须添加一个ORDER BY子句以使您的语句具有确定性。

在这种情况下,在DISTINCT那里它可能会进行哈希聚合 - 从执行到执行,它往往会以不一致的顺序返回结果。即使您正在执行通常按顺序返回结果的索引扫描,您也不能假设它会,除非您告诉 PostgreSQL 您需要按特定顺序排列的行。

这与询问如何以表格的“自然”顺序选择行的人密切相关;表和结果集不具有自然顺序。它们是集合而不是列表。如果您需要排序,则必须在逐个操作的基础上指定一个排序。