Я использую UDF's SQL для инкапсуляции простого создания отчетов/бизнес-логики. Я должен избежать этого?

Я создаю новую базу данных в SQL Server 2008 для некоторого создания отчетов, и существует много общих бизнес-правил, имеющих отношение к этим данным, которые входят в различные типы отчетов. В настоящее время эти правила главным образом объединены в больших процедурных программах на языке прежней версии, который я пытаюсь отодвинуться к SQL. Я стреляю для гибкости в реализации создания отчетов от этих данных, как некоторое создание отчетов в SAS, некоторые в C#, и т.д.

Мой подход в настоящее время должен разбивать эти общие правила (обычно ОЧЕНЬ простая логика) и инкапсулировать их в отдельном SQL UDFs. Производительность не является беспокойством, я просто хочу использовать эти правила заполнить статические поля в своего рода создании отчетов "снимок", который может затем использоваться для создания отчетов от любым способом, которым Вы хотите.

Мне нравится этот модульный подход до понимания, что каждое правило делает (и поддерживает сами правила), но я также начинаю немного пугаться, что обслуживание может также стать кошмаром. Некоторые правила зависят от других, но я не могу действительно убежать от этого - эти вещи сборка друг от друга..., который является тем, что я хочу... Я думаю?;)

Есть ли некоторые лучшие подходы для этого модульного подхода в базе данных? Я на правильном пути, или я думаю об этом в слишком большом количестве мышления разработки приложений?

7
задан chucknelson 28 January 2010 в 22:09
поделиться

5 ответов

SQL устанавливается на основе, и по своей природе плохо выполняется при нанесении модульного подхода.
Функции, хранимые процедуры и / или просмотры - все они абстрактны базовая логика. Проблема производительности вступает в игру, когда вы используете две (или более) функции / и т. Д., Которые используют одну и ту же таблицу (ы). Это означает, что два запроса сделаны та же таблица, когда можно было использовать.

Использование нескольких функций говорит мне, что модель данных была сделана очень «гибкой». Для меня это означает сомнительные данные, набрав и общий определений столбца / таблицы. Существует необходимость в функциях / etc, поскольку база данных позволит что-либо хранить, что означает, что возможность плохих данных очень высока. Я бы предпочел приложить усилия на всегда иметь хорошие / допустимые данные, а не работать после того, как факт бороться с существующими плохими данными.

База данных - это место для содержения этой логики. Это быстрее, чем код приложения, а главное - централизовано для минимизации обслуживания.

1
ответ дан 7 December 2019 в 10:01
поделиться

В какой-то момент широкое использование UDFS начнет вызывать проблемы с производительностью, поскольку они выполняются для каждой строки в ваших результатах и ​​неясной логике из оптимизатора, что делает его трудно использовать индексы (то есть я Не понимаю, как производительность не может быть проблемой, но вы знаете, что ваши требования лучше всего). Для определенных функций они великолепны; Но используйте их экономно.

-121--4013081-

Я бы сказал, что вы находитесь на правильном пути - SQL-процедуры могут быстро выйти из-под контроля, так как становятся все более сложные и инкапсулирующие общие, повторные кусочки логики в UDF Соответствующее решение для решения этого.

Я часто говорю так далеко, что и инкапсулируя логика из процедуры SQL, которая используется только в том, что одна процедура в хорошо называемую UDF для повышения удодоровимости.

Посмотрите на эту статью эта статья MSDN на UDFS - возможно, она даст вам еще несколько представлений об их использовании?

Существует различные соображения производительности, которые вам нужно будет знать, если вы намерены Чтобы использовать UDFS в значительной степени - такие вещи, как производительность скалярных, таблиц UDF и возможные преимущества CLR UDFS.

1
ответ дан 7 December 2019 в 10:01
поделиться

В какой-то момент широкое использование UDF-файлов начнет вызывать проблемы с производительностью, так как они выполняются для каждой строки в вашем результирующем файле и затушевывают логику от оптимизатора, затрудняя использование индексов (т.е. я не совсем понимаю, как производительность может не быть проблемой, но вы лучше знаете свои требования). Для определенного функционала они великолепны, но используйте их экономно.

2
ответ дан 7 December 2019 в 10:01
поделиться

Сохранение логики со стороны БД почти всегда является правильным.

Как Вы уже упоминали в своем вопросе, большинство правил ведения бизнеса подразумевает достаточно простую логику, но, как правило, она касается огромных объемов данных.

Движок БД - правильное решение для реализации этой логики, потому что, во-первых, он сводит данные I/O к минимуму, а, во-вторых, БД выполняет преобразование данных мостов гораздо эффективнее.

Некоторое время назад я написал очень субъективный пост в блоге на эту тему:

Одно примечание: UDF - это не то же самое, что хранимая процедура.

UDF UDF - это функция, созданная вызываемой внутри запроса, поэтому она может выполнять только очень ограниченное подмножество возможных операций.

Вы можете сделать гораздо больше - это хранимая процедура.

Обновление:

В приведенном вами примере, как и изменение логики, вычисляющей "производное поле", UDF, вычисляющий поле, является нормальным.

Но (на всякий случай), когда производительность будет проблемой (и поверьте, это будет гораздо раньше, чем можно подумать), преобразование данных с помощью операций на основе множеств может быть гораздо более эффективным, чем использование UDFs.

В этом случае может понадобиться создать представление, хранимую процедуру или функцию с ценностью таблицы, возвращающую resultet, который будет содержать более эффективный запрос, а не ограничиваться обновлением UDFs (которые основаны на записях).

Один пример: ваш запрос имеет нечто вроде "оценки пользователя", которую вы считаете подверженной изменениям, и оберните ее в UDF

SELECT  user_id, fn_getUserScore(user_id)
FROM    users

Изначально это простое поле в таблице:

CREATE FUNCTION fn_getUserScore(@user_id INT) RETURNS INT
AS
BEGIN
        DECLARE @ret INT
        SELECT  user_score
        INTO    @ret
        FROM    users
        WHERE   user_id = @user_id
        RETURN @ret
END

, затем вы решаете вычислить его, используя данные из другой таблицы:

CREATE FUNCTION fn_getUserScore(@user_id INT) RETURNS INT
AS
BEGIN
        DECLARE @ret INT
        SELECT  SUM(vote)
        INTO    @ret
        FROM    user_votes
        WHERE   user_id = @user_id
        RETURN @ret
END

Это обрекает движок на использование наименее эффективного алгоритма NESTED LOOPS в обоих случаях.

Но если бы вы создали представление и переписали лежащие в его основе запросы следующим образом:

SELECT  user_id, user_score
FROM    users

SELECT  user_id, SUM(vote) AS user_score
FROM    users u
LEFT JOIN
        user_votes uv
ON uv.user_id = u.user_id

, то это дало бы движку гораздо больше места для оптимизации, сохранив при этом структуру resultet'ов и отделив логику от представления.

2
ответ дан 7 December 2019 в 10:01
поделиться

Если Вам интересно построить хранилище данных для составления отчетов, Вы постараетесь поместить как можно больше этого в трансформируемую часть Вашей ETL, чтобы Ваш SQL отчет состоял из простых операторов, которые могут быть сгенерированы как инструментами, так и пользователями.

SSIS - очень мощный инструмент для ETL, который поставляется с SQL-сервером для таких вещей.

0
ответ дан 7 December 2019 в 10:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: