Reputation: 601
I have materialized view and it's very helpful. But after some time of using it I got issue that order in view is broken. I created Matview as:
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);
ORDER BY in my case is very important thing, so it works when I query from Matview and got sorted result of joining tables:
SELECT id FROM mat_view_sorted_products
LIMIT 100 OFFSET 0; //got 100 sorted item ids by (is_available DESC, views DESC)
To refresh Materialized view I use: REFRESH MATERIALIZED VIEW CONCURRENTLY mat_view_sorted_products
But after some time and many refreshing iterations I saw that the order of matview records is broken. I thought that CONCURRENTLY updates values of free (of reading) records and do not change anything else.
Not? How is it working and how not to break ORDER while refreshing View?
P.S.
if I do REFRESH without CONCURRENTLY it restores normal sorting. It blocks view, cleans it and restores from select with order. But users do not have time to wait each time View is refreshing
UPDATE:
Of course I use order in my full SELECT statement:
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;
And it makes Sequence Scan on mat_view_sorted_products and I got 100 sorted items of all sorted items in view. As I think the view creates like:
Upvotes: 1
Views: 1711
Reputation:
No, the order is "not broken" because there is no such thing as the "order" of rows in a table.
Tables (and that includes materialized views) represent unorder sets and they have no implied order.
The only way to get a guaranteed sort order is to use order by
in your SELECT statement. There is no alternative.
Remove the order by
from your CREATE MATERIALIZED view statement and add it to your actual SELECT
statement. Using LIMIT or OFFSET without an ORDER BY
is a bug in your code.
Upvotes: 8