Ниже приведен отрывок из книги о дизайне БД (Начальный номер базы данных ISBN: 0-7645-7490-6):
Опасность использования представлений заключается в фильтрации запроса к представлению, ожидающего чтения очень маленькой части очень большой таблицы. Любая фильтрация должна выполняться в представлении, поскольку любая фильтрация для самого представления применяется после того, как запрос в представлении завершил выполнение. Представления обычно полезны для ускорения процесса разработки, но в долгосрочной перспективе могут полностью снизить производительность базы данных.
Ниже приводится выдержка из документации PostgreSQL 9.5:
Либеральное использование представлений является ключевым аспектом хорошего дизайна базы данных SQL. Представления позволяют инкапсулировать детали структуры ваших таблиц, которые могут меняться по мере развития вашего приложения, за согласованными интерфейсами.
Два источника, кажется, противоречат друг другу («не проектируйте с помощью представлений» и «не проектируйте с помощью представлений»).
Однако в PG представления реализованы с использованием системы правил. Таким образом, возможно (и это мой вопрос) любая фильтрация по представлению переписывается как фильтр внутри представления, что приводит к одному выполнению запроса к базовым таблицам.
Верна ли моя интерпретация, и PG комбинирует предложения WHERE в поле зрения и из поля зрения? Или он запускает их отдельно, один за другим? Какие-нибудь короткие, самодостаточные, правильные (компилируемые) примеры?
SELECT * FROM my_view WHERE my_column = 'blablabla';
:. Второй - об использовании представлений, чтобы сделать вашу модель данных прозрачной для приложения, которое ее использует. Первые источники указывают, что вы должны включить фильтрWHERE my_column = 'blablabla'
в определение представления, так как это приведет к лучшему плану выполнения.Ответы:
Книга не права.
Выбор в представлении происходит так же быстро или медленно, как и выполнение основного оператора SQL - вы можете легко проверить это, используя
explain analyze
.Оптимизатор Postgres (и оптимизатор для многих других современных СУБД) сможет выдвигать предикаты в представлении в фактическое утверждение представления - при условии, что это простое утверждение (опять же, это можно проверить с помощью
explain analyze
).«Плохая репутация» в отношении производительности возникает, я думаю, из-за того, что вы злоупотребляете представлениями и начинаете создавать представления, использующие представления, использующие представления. Очень часто это приводит к операторам, которые делают слишком много по сравнению с оператором, который был составлен вручную без представлений, например, потому что некоторые промежуточные таблицы не понадобятся. Практически во всех случаях оптимизатор недостаточно умен, чтобы удалять эти ненужные таблицы / объединения или опускать предикаты для нескольких уровней представлений (это верно и для других СУБД).
источник
explain analyze
утверждение?Чтобы дать вам пример того, что объяснил @a_horse :
Postgres реализует информационную схему, которая состоит из (иногда сложных) представлений, предоставляющих информацию об объектах БД в стандартизированной форме. Это удобно и надежно - и может быть значительно дороже, чем прямой доступ к таблицам каталога Postgres.
Очень простой пример, чтобы получить все видимые столбцы таблицы
... из информационной схемы:
... из системного каталога:
Сравните планы запросов и время выполнения для обоих
EXPLAIN ANALYZE
.Первый запрос основан на представлении
information_schema.columns
, которое объединяет несколько таблиц, в которых мы вообще не нуждаемся.Второй запрос сканирует только одну таблицу
pg_catalog.pg_attribute
, следовательно, намного быстрее. (Но для первого запроса все еще требуется всего несколько мс в обычных БД.)Детали:
источник
РЕДАКТИРОВАТЬ:
С извинениями мне нужно отозвать свое утверждение о том, что принятый ответ не всегда верен - он утверждает, что представление всегда идентично тому же, что написано в качестве подзапроса. Я думаю, что это неоспоримо, и я думаю, что теперь я знаю, что происходит в моем случае.
Теперь я также думаю, что есть лучший ответ на оригинальный вопрос.
Первоначальный вопрос заключается в том, следует ли руководствоваться практикой использования представлений (в отличие, например, от повторения SQL в подпрограммах, которые, возможно, потребуется поддерживать дважды или более).
Мой ответ будет «нет, если ваш запрос использует оконные функции или что-то еще, что заставляет оптимизатор по-разному относиться к запросу, когда он становится подзапросом, потому что сам процесс создания подзапроса (независимо от того, представлен ли он как представление или нет) может снизить производительность если вы фильтруете с параметрами во время выполнения.
Сложность моей оконной функции не нужна. Объясните план для этого:
гораздо дешевле, чем для этого:
Надеюсь, это будет более конкретным и полезным.
По моему недавнему опыту (заставляя меня найти этот вопрос), принятый ответ выше не является правильным при всех обстоятельствах. У меня есть относительно простой запрос, который включает в себя функцию окна:
Если я добавлю этот фильтр:
План объяснения, который я получаю, выглядит следующим образом:
При этом используется индекс первичного ключа в таблице обслуживания поездов и неуникальный индекс в таблице part_consist. Выполняется за 90мс.
Я создал представление (вставив его здесь, чтобы быть абсолютно ясным, но это буквально запрос в представлении):
Когда я запрашиваю это представление с идентичным фильтром:
Это план объяснения:
Это делает полное сканирование обеих таблиц и занимает 17 секунд.
Пока я не столкнулся с этим, я свободно использовал представления с PostgreSQL (поняв широко распространенные взгляды, выраженные в принятом ответе). Я бы специально избегал использования представлений, если мне нужна предварительная агрегационная фильтрация, для которой я бы использовал функции, возвращающие множество.
Мне также известно, что CTE в PostgreSQL строго оцениваются отдельно, в зависимости от проекта, поэтому я не использую их так же, как с SQL Server, например, где они, кажется, оптимизированы как подзапросы.
Поэтому мой ответ таков: есть случаи, когда представления не работают точно так, как запрос, на котором они основаны, поэтому рекомендуется соблюдать осторожность. Я использую Amazon Aurora на основе PostgreSQL 9.6.6.
источник
CASE WHEN (NOT ts.primary_direction) THEN '-1' :: INTEGER ELSE 1 END
что излишне делать запрос медленнее, чем нужно, если вам лучше написать еще два условия в порядке.CASE WHEN (NOT ts.primary_direction) THEN dense_rank() OVER (PARTITION BY ts.train_service_key ORDER BY pc.through_idx DESC, pc.first_portion ASC, pc.first_seq DESC) ELSE dense_rank() OVER (PARTITION BY ts.train_service_key ORDER BY pc.through_idx DESC, pc.first_portion ASC, pc.first_seq ASC) END AS coach_block_idx
dense_rank()
так что это не проблема производительности.(Я большой поклонник представлений, но вы должны быть очень осторожны с PG здесь, и я хотел бы призвать всех использовать представления в целом также в PG для лучшей понятности и удобства запросов / кода)
На самом деле и к сожалению (ПРЕДУПРЕЖДЕНИЕ :) использование представлений в Postgres вызвало у нас реальные проблемы и сильно снизило нашу производительность в зависимости от функций, которые мы использовали внутри него :-( (по крайней мере, с v10.1). (Это было бы не так с другими современные системы баз данных, такие как Oracle.)
(В зависимости от того, что именно вы имеете в виду - промежуточные временные таблицы могут быть материализованы, что вы, возможно, не хотите, или где предикаты не помещены вниз ...)
Я знаю, по крайней мере, две основные "особенности", которые подводят нас к середине миграции с Oracle на Postgres, поэтому нам пришлось отказаться от PG в проекте:
CTE (
with
подзапросы -clause / общие табличные выражения ) (обычно) полезны для структурирования более сложных запросов (даже в небольших приложениях), но в PG они спроектированы как «скрытые» подсказки оптимизатора (генерирующие, например, неиндексированные временные таблицы) и таким образом нарушают (для меня и многих других важных) концепцию декларативного SQL ( документ Oracle ): например,простой запрос:
переписан с использованием некоторого CTE:
другие источники с обсуждениями и т.д .: https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/
оконные функции с
over
-statements потенциально непригодны (обычно используются в представлениях, например, как источник для отчетов, основанных на более сложных запросах)наш обходной путь для
with
клаузулМы преобразуем все «встроенные представления» в реальные представления со специальным префиксом, чтобы они не мешали списку / пространству имен представлений и могли быть легко связаны с исходным «внешним видом»: - /
наше решение для оконных функций
Мы успешно реализовали его, используя базу данных Oracle.
источник