Вопросы производительности для триггеров и ограничений

StackOverflow https://stackoverflow.com/questions/148129

Вопрос

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

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

Это было полезно?

Решение

Ограничения опускаются!

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

  • С помощью триггеров вы указываете, как обрабатывать данные (при вставках, обновлениях и т. д.).Это «нереляционный» способ ведения дел.

Чтобы лучше объяснить себя аналогией:Правильный способ написания SQL-запроса — указать «что вы хотите», а не «как это получить» — пусть СУБД сама выберет лучший способ сделать это за вас.То же самое применимо и здесь:если вы используете триггеры, вам нужно помнить о различных вещах, таких как порядок выполнения, каскадирование и т. д.Позвольте SQL сделать это за вас с ограничениями, если это возможно.

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

Другие советы

Лучшая практика:если вы можете сделать это с ограничением, используйте ограничение.

Триггеры не так уж и плохи, как их дискредитируют (при правильном использовании), хотя я бы всегда использовал ограничение там, где это возможно. В современной RDMS издержки производительности триггеров сравнимы с ограничениями. (конечно, это не значит, что кто-то не может поместить в триггер ужасный код!).

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

Споры о том, должна ли бизнес-логика размещаться в приложении, а не в БД, в некоторой степени зависят от среды;если у вас есть много приложений, обращающихся к БД, как ограничения, так и триггеры могут служить последней гарантией правильности данных.

Триггеры могут перерасти в проблемы с производительностью.Примерно в то же время, когда это происходит, они также стали кошмаром для обслуживания.Вы не можете понять, что происходит и (бонус!) Приложение ведет себя хаотично с «ложными» проблемами с данными.[Действительно, это проблемы с триггером.]

Ни один конечный пользователь не касается SQL напрямую.Они используют прикладные программы.Прикладные программы содержат бизнес-логику гораздо более разумным и удобным в сопровождении образом, чем триггеры.Поместите логику приложения в прикладные программы.Поместите данные в базу данных.

Если вы и ваши «пользователи» не говорите на одном языке, вы можете объяснить им нарушения ограничений.Альтернатива (не объясняющая) превращает простую базу данных в проблему, поскольку объединяет данные и код приложения в неразрешимую трясину.

«Как мне получить абсолютную уверенность в том, что все правильно используют модель данных?»

Две (с половиной) техники.

  1. Убедитесь, что модель верно:он соответствует реальной проблемной области.Никаких хаков, обходных путей или ярлыков, которые можно решить только с помощью сложных объяснений, хранимых процедур и триггеров.

  2. Помогите определить уровень бизнес-модели приложений.Уровень кода приложения, который все используют совместно и повторно.

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

Триггеры — это крушение поезда, ожидающее своего часа.Ограничений нет.

В дополнение к другим причинам использования ограничений оптимизатор Oracle может использовать ограничения в своих интересах.

Например, если у вас есть ограничение, говорящее (Amount >= 0) а затем вы запрашиваете с помощью WHERE (Amount = -5) Oracle сразу узнает, что совпадающих строк нет.

Ограничения и триггеры предназначены для двух разных вещей.Ограничения используются для сдерживать домен (действительные входные данные) ваших данных.Например, SSN будет храниться как char(9), но с ограничением [0-9][0-9][0-9][0-9][0-9][0-9][ 0-9][0-9][0-9] (все числовые).

Триггеры – это способ принуждения к бизнесу логика в вашей базе данных.Возвращаясь к SSN, возможно, необходимо вести контрольный журнал при каждом изменении SSN - это можно сделать с помощью триггера,

В общем, проблемы целостности данных в современной СУБД могут быть решены с помощью некоторых вариаций ограничений.Однако иногда вы попадаете в ситуацию, когда неправильная нормализация (или изменение требований, приводящее к неправильной нормализации) препятствует ограничению.В этом случае триггер может обеспечить соблюдение вашего ограничения, но он непрозрачен для СУБД, то есть его нельзя использовать для оптимизации.Это также «скрытая» логика, которая может стать проблемой при обслуживании.На этом этапе необходимо принять решение о рефакторинге схемы или использовании триггера.

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

@onedaywhen

Вы можете использовать запрос в качестве ограничения в SQL Server, вам просто нужно поместить его в скалярную функцию:http://www.eggheadcafe.com/software/aspnet/30056435/check-contraints-and-tsql.aspx

@Марк Брэкетт:«Ограничения используются для ограничения домена...Триггеры — это способ реализации бизнес-логики»:В SQL Server все не так просто, потому что функциональность его ограничений ограничена, например.еще не полный SQL-92.Возьмем классический пример последовательного «первичного ключа» во временной таблице базы данных:в идеале я бы использовал ограничение CHECK с подзапросом, чтобы предотвратить перекрытие периодов для одного и того же объекта, но SQL Server не может этого сделать, поэтому мне приходится использовать триггер.В SQL Server также отсутствует возможность SQL-92 откладывать проверку ограничений, но вместо этого они (фактически) проверяются после каждого оператора SQL, поэтому для обхода ограничений SQL Server снова может потребоваться триггер.

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

Что касается того, следует ли помещать логику в приложение вместо триггера или ограничения.НЕ ДЕЛАЙ ЭТОГО!!!Да, приложения должны проверяться перед отправкой данных, но целостность данных и бизнес-логика должны быть на уровне базы данных, иначе ваши данные будут испорчены, когда к ним подключаются несколько приложений, когда глобальные вставки выполняются вне приложения и т. д.Целостность данных является ключом к базам данных и должна обеспечиваться на уровне базы данных.

@Мефф:существуют потенциальные проблемы с подходом к использованию функции, потому что, проще говоря, ограничения SQL Server CHECK были разработаны с одной строкой в ​​качестве единицы работы и имеют недостатки при работе с набором результатов.Более подробную информацию об этом см.:[http://blogs.conchango.com/davidportas/archive/2007/02/19/Trouble-with-CHECK-Constraints.aspx][1].

[1]:Блог Дэвида Портаса:Проблема с ограничениями CHECK.

То же, что Скливз.Просто чтобы вы знали каноническое использование триггера таблица аудита.Если многие процедуры обновляют/вставляют/удаляют таблицу, которую вы хотите проверить (кто, что и когда изменил), триггер — самый простой способ сделать это.Один из способов — просто добавить флаг в вашу таблицу (активный/неактивный с некоторым ограничением уникальности) и вставить что-нибудь в таблицу аудита.

Другой способ, если вы хотите, чтобы таблица не содержала исторические данные, — это скопировать предыдущую строку в вашей таблице аудита...

У многих людей есть много способов сделать это.Но одно можно сказать наверняка: вам придется выполнять вставку для каждого обновления/вставки/удаления в этой таблице.

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

Я согласен со всеми здесь по поводу ограничений.Используйте их как можно больше.

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

При этом триггеры имеют свое место и их следует использовать при необходимости.Они особенно хороши для отслеживания изменений в данных (как упомянул Марк Брэкетт).Вам нужно ответить на вопрос: «Где имеет смысл разместить мою бизнес-логику»?В большинстве случаев я думаю, что это должно быть в кодексе, но нужно сохранять непредвзятость.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top