#postgresql #postgresql-9.5 #materialized-views
#postgresql #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);
ПОРЯДОК в моем случае очень важен, поэтому он работает, когда я запрашиваю из Matview и получаю отсортированный результат объединения таблиц:
SELECT id FROM mat_view_sorted_products
LIMIT 100 OFFSET 0; //got 100 sorted item ids by (is_available DESC, views DESC)
Для обновления материализованного представления я использую: REFRESH MATERIALIZED VIEW CONCURRENTLY mat_view_sorted_products
Но через некоторое время и множество обновляющих итераций я увидел, что порядок записей matview нарушен. Я думал, что это ОДНОВРЕМЕННО обновляет значения свободных (для чтения) записей и ничего больше не меняет.
Нет? Как это работает и как не нарушать ПОРЯДОК при обновлении представления?
Постскриптум
если я выполняю ОБНОВЛЕНИЕ без ОДНОВРЕМЕННОГО восстановления нормальной сортировки. Он блокирует представление, очищает его и восстанавливает из select с помощью order . Но у пользователей нет времени ждать каждый раз, когда обновляется представление
Обновить:
Конечно, я использую порядок в своем полном операторе ВЫБОРА:
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;
И он выполняет сканирование последовательности в mat_view_sorted_products, и я получил 100 отсортированных элементов всех отсортированных элементов в поле зрения.
Как я думаю, представление создает:
- получил 200 элементов, заказанных … из AS SELECT
- вставил их в MatView
- выполнение сканирования seq для 200 отсортированных элементов, чтобы получить первые 100 отсортированных элементов из всех
Комментарии:
1. Поскольку материализованные представления — это просто таблицы, у них нет порядка. Вы должны указать порядок в своем
SELECT
запросе.
Ответ №1:
Нет, порядок «не нарушен», потому что в таблице нет такого понятия, как «порядок» строк.
Таблицы (и это включает в себя материализованные представления) представляют неупорядоченные наборы, и они не имеют подразумеваемого порядка.
Единственный способ получить гарантированный порядок сортировки — использовать order by
в вашем операторе ВЫБОРА. Альтернативы нет.
Удалите order by
из вашего оператора CREATE MATERIALIZED view и добавьте его в свой фактический SELECT
оператор. Использование LIMIT или OFFSET без an ORDER BY
является ошибкой в вашем коде.
Комментарии:
1. Пожалуйста, следите за обновлением
2. @НиколайАгеев Ваш подзапрос, который использует
LIMIT
иOFFSET
все еще не используетORDER BY
. Порядок by во внешнем запросе не имеет значения для предложений limit и offset3. Если я вставлю отсортированный результат в новый / чистый вид, зачем мне нужно повторять сортировку записей после него? Сканирование последовательности будет проходить через отсортированную таблицу при выборе из представления
4. Опять же: единственный способ получить гарантированный порядок сортировки — использовать
order by
. Если вы получили отсортированный результат до сих пор, это было чистое совпадение и могло измениться в любое время, например, когда одновременно выполняются два последовательных сканирования в одной таблице. Единственный способ получить гарантированный порядок сортировки — использоватьORDER BY
— альтернативы нет .5. Поэтому, когда я создаю материализованный вид, мне не нужно использовать ORDER в AS .. (поскольку это бессмысленно), да?