💡如果在物化视图定义的查询语句中指定了 ORDER BY 子句,刷新物化视图数据时不会保证数据仍然按照指定顺序进行存储。
💡虽然物化视图定义中的查询语句支持 ORDER BY 子句,但是不推荐使用。如果想要以指定顺序显示数据,应该在查询数据时明确指定排序字段,而不应该依赖表中的数据存储顺序。
简而言之,如果要使用物化视图的话,最好在定义的时候不使用 ORDER BY 子句,因为在刷新的时候,无法保证数据仍然有序。这不,又了解到一个新知识,之前也不曾关注过。
翻了一下官方文档,也确实有这么一段说明:
If there is an ORDER BY clause in the materialized view’s defining query, the original contents of the materialized view will be ordered that way; but REFRESH MATERIALIZED VIEW does not guarantee to preserve that ordering.
验证
复现一下,随机插入 10 条数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
postgres=# create table t1(id int); CREATE TABLE postgres=# insert into t1 select n from generate_series(10,50) as n orderby random() limit 10; INSERT010 postgres=# select*from t1; id ---- 24 27 36 16 49 30 28 50 35 29 (10rows)
postgres=# truncatetable t1; TRUNCATETABLE postgres=# insert into t1 select n from generate_series(10,50) as n orderby random() limit 10; INSERT010 postgres=# create materialized view mt1 asselect*from t1 orderby id; SELECT10 postgres=# createunique index on mt1(id); CREATE INDEX
所以,这种方式就无法再去保证数据的有序性了,当然你说在其中某个阶段,再去做一个 order by 不就行了?确实如此,但是这样,我想无疑就会使得 concurrently 的效率再进一步大打折扣 (貌似有点牵强?)。关于这块的细节,读者可以参考 refresh_by_match_merge(),代码逻辑还是比较清晰的
评论区按需加载,正文阅读不会被第三方服务拖慢。