Postgresql 刷新物化视图同时打破顺序

Nik*_*eev 1 postgresql materialized-views postgresql-9.5

我有物化视图,它非常有帮助。但使用一段时间后,我遇到了问题,视图中的顺序被破坏了。我将 Matview 创建为:

CREATE MATERIALIZED VIEW mat_view_sorted_products AS
      SELECT item.id, item.category_id FROM item
      INNER JOIN stock ON stock.item_id = item.id
      ORDER BY is_available DESC, views DESC;

CREATE UNIQUE INDEX mat_view_index_id ON mat_view_sorted_products (id);
Run Code Online (Sandbox Code Playgroud)

ORDER BY 在我的例子中是非常重要的事情,所以当我从 Matview 查询并获得连接表的排序结果时它会起作用:

SELECT id FROM mat_view_sorted_products
LIMIT 100 OFFSET 0; //got 100 sorted item ids by (is_available DESC, views DESC)
Run Code Online (Sandbox Code Playgroud)

要刷新物化视图,我使用:REFRESH MATERIALIZED VIEW CONCURRENTLY mat_view_sorted_products

但经过一段时间和多次刷新迭代后,我发现 matview 记录的顺序被打破了。我认为同时更新空闲(读取)记录的值并且不更改其他任何内容。

不是?它是如何工作的以及如何在刷新视图时不破坏订单?

聚苯乙烯

如果我在没有并发的情况下进行刷新,它会恢复正常排序。它会阻止视图、清理视图并按顺序从选择中恢复。但用户没有时间每次View刷新时都等待

更新:

当然,我在完整的 SELECT 语句中使用顺序:

SELECT id, name, views FROM item WHERE id IN (SELECT id FROM mat_view_sorted_products
LIMIT 100 OFFSET 0) ORDER BY is_available DESC, views DESC;
Run Code Online (Sandbox Code Playgroud)

它对 mat_view_sorted_products 进行序列扫描,我得到了视图中所有排序项目的 100 个排序项目。我认为视图创建如下:

  1. 从 AS SELECT 中获得了 ... 订购的 200 件商品
  2. 将它们插入 MatView 中
  3. 对 200 个排序项进行 seq 扫描,以获取所有排序项的前 100 个

小智 7

不,顺序“没有被破坏”,因为表中不存在行的“顺序”。

表(包括物化视图)表示无序集,并且它们没有隐含的顺序。

获得有保证的排序顺序的唯一方法是order by在 SELECT 语句中使用。没有替代。

order by从 CREATE MATERIALIZED 视图语句中删除并将其添加到实际SELECT语句中。使用不带LIMIT 或 OFFSET 的代码ORDER BY是代码中的错误。