Миграция ActiveRecord не заполняет материализованное представление Postgres
У меня есть MATERIALIZED VIEW
это создается с помощью миграции.
class MyView < ActiveRecord::Migration
def up
ActiveRecord::Base.connection.execute <<-SQL
CREATE MATERIALIZED VIEW my_view AS (
SELECT DISTINCT something, something_else, other.thing as real_thing, thing.some_id
FROM some_table
JOIN another_table on another_table.id = something
JOIN one_more_table on some_table.id = other_id
ORDER BY order_column)
WITH DATA;
SQL
add_index :table, [:key_part_one, :key_part_two]
end
...
end
Примечание: я запутал оператор SELECT, просто поверьте мне, что он работает.
Здесь важно отметить, что я явно назвал WITH DATA
, поэтому представление должно быть заполнено и сканируемо сразу.
Этого не происходит. Миграция выполняется, как показано ниже
== MyView: migrating ========================
== MyView: migrated (0.0763s) ===============
Позже в db:refresh
мы видим следующее
Reindexing Something...
Reindex queued
Reindexing Another...
Reindex queued
Reindexing SomeOtherThing...
Reindex queued
Reindexing One::OtherThing...
Reindex queued
Reindexing MyViewModel...
rake aborted!
ActiveRecord::StatementInvalid: PG::ObjectNotInPrerequisiteState: ERROR: materialized view "my_view" has not been populated
HINT: Use the REFRESH MATERIALIZED VIEW command.
Хм что? Я объявил WITH DATA
, У меня также есть другая последовательная миграция, которая явно вызывает REFRESH MATERIALIZED VIEW
Команда на вид.
Безрезультатно, чтобы завершить задачу rake db: refresh, я должен войти и вручную обновить представление.
Интересное примечание: в файле Structure.sql он показан как созданный без данных.
CREATE MATERIALIZED VIEW my_view AS (
SELECT DISTINCT something, something_else, other.thing as real_thing, thing.some_id
FROM some_table
JOIN another_table on another_table.id = something
JOIN one_more_table on some_table.id = other_id
ORDER BY order_column)
WITH NO DATA;
Я считаю, что это реальная проблема, но я не знаю, как исправить / обойти. Это также сбивает с толку, потому что даже если он был создан без данных, последующий REFRESH MATERIALIZED VIEW должен заполнить его и пометить как сканируемый.
Есть ли какая-то проблема с Postgres или AR, о которой я не знаю, которая мешает мне заполнить это материализованное представление?
1 ответ
Я знаю, что вопрос задавался почти 2 года назад, но, возможно, мой ответ будет полезен для кого-то еще.
Попробуйте использовать сценический драгоценный камень. Я недавно написал в блоге об этом.
Я считаю, что вам нужно настроить свою собственную стратегию для вызова refresh
на материализованных взглядах. У сценического драгоценного камня есть метод освежения, который стоит изучить.
Вы можете посмотреть перед хуками (для спецификаций / тестов) или грабли перед задачами хуков, чтобы сделать это обновление немного более безболезненным (автоматическое объединение в цепочку после вызова migrate
, например)
Интересно, что дампы Postgres (через pg_dump
команда) материализованные представления созданы WITH DATA
как WITH NO DATA
также. Я не уверен, что основная причина, но я предполагаю, что это работает как задумано, основываясь на цели запуска дампа.
Тем не мение, pg_dump
Также включает в себя REFRESH
Команда в дамп-файле (rails не делает), поэтому вам нужно придумать свою собственную стратегию обновления материализованного представления.
После дальнейших раскопок я заметил --schema-only
флаг передан pg_dump
Команда не будет сбрасывать REFRESH MATERIALIZED VIEW
команда. Рельсы db:structure:dump
Команда для Postgres, кажется, использует эту команду (как -s
). Этого может быть достаточно, чтобы помочь вам определить способ изменить поведение, но я думаю, что другой ответ рекомендует использовать scenic
, в сочетании с некоторыми рейк-задачами для автоматического обновления может быть лучшим выбором.