Ответ 1
Функции таблицы
Я выполняю очень высокую скорость, сложные миграции баз данных для жизни, используя SQL как язык клиента и сервера (не используется какой-либо другой язык), все на стороне сервера, где код редко выходит из механизма базы данных. Функции таблицы играют большую роль в моей работе. Я не использую "курсоры", так как они слишком медленны, чтобы соответствовать моим требованиям к производительности, и все, что я делаю, ориентировано на результат. Функции таблицы оказали мне огромную помощь в полном устранении использования курсоров, достижении очень высокой скорости и значительно способствовали уменьшению объема кода и улучшению простоты.
Короче говоря, вы используете запрос, который ссылается на две (или более) функции таблицы для передачи данных из одной таблицы в другую. Набор результатов запроса выбора, вызывающий функции таблицы, служит в качестве канала для передачи данных из одной таблицы в следующую. На платформе/версии DB2 я работаю, и она появляется на основе быстрого посмотрите в руководстве 9.1 Postgres, что там же верно, вы можете передавать только одну строку значений столбцов в качестве входных данных для любого вызова вызовов в таблице, как вы обнаружили. Однако, поскольку вызов функции таблицы происходит в середине обработки набора результатов запроса, вы достигаете того же эффекта передачи всего набора результатов каждому вызову функции таблицы, хотя в системе обработки данных базы данных данные передаются только одна строка за раз для каждой функции таблицы.
Функции таблицы принимают одну строку входных столбцов и возвращают один результат обратно в вызывающий запрос (т.е. select), который вызывает функцию. Столбцы набора результатов, возвращенные из функции таблицы, становятся частью набора результатов вызывающего запроса и поэтому доступны в качестве входных данных для следующей функции таблицы, упомянутой позже в том же запросе, как правило, в качестве последующего объединения, Первые столбцы результатов функции таблицы подаются как входные данные (по одной строке за раз) во вторую функцию таблицы, которая возвращает столбцы набора результатов в набор результатов вызывающего запроса. И первый, и второй столбец результатов функции таблицы теперь являются частью набора результатов вызывающего запроса и теперь доступны как вход (по одной строке за раз) для третьей функции таблицы. Каждый вызов функции таблицы расширяет набор результатов вызывающего запроса через столбцы, которые он возвращает.. Это может продолжаться до тех пор, пока вы не нажмете ограничения на ширину набора результатов, который, вероятно, будет варьироваться от одного механизма базы данных до следующий.
Рассмотрим этот пример (который может не соответствовать синтаксическим требованиям или возможностям Postgres при работе с DB2). Это один из многих шаблонов проектирования, в котором я использую функции таблицы, является одним из более простых, который я считаю очень показательным, и тот, который, как я ожидал, имел бы широкую привлекательность , если функции таблицы были в тяжелом (насколько мне известно, это не так, но я думаю, что они заслуживают большего внимания, чем получают).
В этом примере используемые функции таблицы: VALIDATE_TODAYS_ORDER_BATCH, POST_TODAYS_ORDER_BATCH и DATA_WAREHOUSE_TODAYS_ORDER_BATCH. В версии DB2, над которой я работаю, вы закрываете функцию таблицы внутри "TABLE (вызов функции таблицы таблицы и параметры здесь)", но, основываясь на быстром просмотре руководства Postgres, вы опускаете оболочку "TABLE()".
create table TODAYS_ORDER_PROCESSING_EXCEPTIONS as (
select TODAYS_ORDER_BATCH.*
,VALIDATION_RESULT.ROW_VALID
,POST_RESULT.ROW_POSTED
,WAREHOUSE_RESULT.ROW_WAREHOUSED
from TODAYS_ORDER_BATCH
cross join VALIDATE_TODAYS_ORDER_BATCH ( ORDER_NUMBER, [either pass the remainder of the order columns or fetch them in the function] )
as VALIDATION_RESULT ( ROW_VALID ) --example: 1/0 true/false Boolean returned
left join POST_TODAYS_ORDER_BATCH ( ORDER_NUMBER, [either pass the remainder of the order columns or fetch them in the function] )
as POST_RESULT ( ROW_POSTED ) --example: 1/0 true/false Boolean returned
on ROW_VALIDATED = '1'
left join DATA_WAREHOUSE_TODAYS_ORDER_BATCH ( ORDER_NUMBER, [either pass the remainder of the order columns or fetch them in the function] )
as WAREHOUSE_RESULT ( ROW_WAREHOUSED ) --example: 1/0 true/false Boolean returned
on ROW_POSTED = '1'
where coalesce( ROW_VALID, '0' ) = '0' --Capture only exceptions and unprocessed work.
or coalesce( ROW_POSTED, '0' ) = '0' --Or, you can flip the logic to capture only successful rows.
or coalesce( ROW_WAREHOUSED, '0' ) = '0'
) with data
- Если таблица TODAYS_ORDER_BATCH содержит 1 000 000 строк, то VALIDATE_TODAYS_ORDER_BATCH будет называться 1,000,000 раз, один раз для каждый ряд.
- Если 900 000 строк проходят проверку внутри VALIDATE_TODAYS_ORDER_BATCH, тогда POST_TODAYS_ORDER_BATCH будет называться 900 000 раз.
- Если успешно опубликовано только 850 000 строк, то VALIDATE_TODAYS_ORDER_BATCH нуждается в некоторых лазейках, закрытых LOL, а DATA_WAREHOUSE_TODAYS_ORDER_BATCH будет называться 850 000 раз.
- Если 850 000 строк успешно попали в хранилище данных (т.е. никаких дополнительных исключений не было создано), то таблица TODAYS_ORDER_PROCESSING_EXCEPTIONS будет заполнена 1 000 000 - 850 000 = 150 000 строк исключений.
Вызов функции таблицы в этом примере возвращает только один столбец, но они могут возвращать много столбцов. Например, функция таблицы, проверяющая строку порядка, может вернуть причину неудачной проверки порядка.
В этом проекте практически вся болтовня между HLL и базой данных устранена, так как запросчик HLL просит базу данных обрабатывать всю партию в ОДНОМ запросе. Это приводит к сокращению миллионов запросов SQL к базе данных, в ОГРОМНОМ удалении миллионов вызовов процедур или вызовов HLL и, как результат, обеспечивает ОГРОМНОЕ улучшение выполнения. Напротив, устаревший код, который часто обрабатывает одну строку за раз, обычно отправляет 1 000 000 выборочных SQL-запросов, 1 для каждой строки в TODAYS_ORDER_BATCH, плюс не менее 1 000 000 запросов HLL и/или SQL для целей проверки, плюс не менее 1 000 000 HLL и/или SQL-запросы для целей проводки, плюс 1 000 000 запросов HLL и/или SQL для отправки заказа в хранилище данных. Конечно, используя эту конструкцию табличной функции, внутри функции таблицы запросы SQL отправляются в базу данных, но когда база данных делает запросы к себе (т.е. Изнутри функции таблицы), запросы SQL обслуживаются гораздо быстрее (особенно по сравнению с устаревший сценарий, когда запросчик HLL выполняет обработку одной строки из удаленной системы, причем наихудший случай над WAN-OMG, пожалуйста, не делайте этого).
Вы можете легко столкнуться с проблемами производительности, если используете функцию таблицы для "выборки набора результатов", а затем присоедините этот результирующий набор к другим таблицам. В этом случае оптимизатор SQL не может предсказать, какой набор строк будет возвращен из функции таблицы, и поэтому он не может оптимизировать объединение к последующим таблицам. По этой причине я редко использую их для получения набора результатов, если только я не знаю, что набор результатов будет очень маленьким числом строк, следовательно, это не вызовет проблемы с производительностью, или мне не нужно присоединяться к последующим таблицам.
По моему мнению, одна из причин недоиспользования функций таблицы заключается в том, что они часто воспринимаются как инструмент для набора результатов, который часто выполняется плохо, поэтому они списываются как "плохой" инструмент для использования.
Функции таблицы чрезвычайно полезны для того, чтобы направить больше функций на сервер, устраняя большую часть болтовни между сервером базы данных и программами на удаленных системах и даже устраняя болтовню между сервером базы данных и внешними программами на том же сервере. Даже болтовня между программами на одном сервере несет больше накладных расходов, чем многие люди понимают, и большая часть из них не нужна. Сердце силы функций таблицы заключается в их использовании для выполнения действий внутри обработки набора результатов.
Существуют более продвинутые шаблоны проектирования для использования функций таблицы, которые основываются на вышеприведенном шаблоне, где вы можете максимизировать обработку набора результатов еще больше, но этот пост для большинства больше всего подходит.