Рекомендации по производительности для триггеров и ограничений
Я пытаюсь выяснить, следует ли использовать критически важную бизнес-логику в триггер или ограничение внутри моей базы данных.
До сих пор я добавил логику в триггеры, поскольку она дает мне контроль над тем, что происходит дальше, и означает, что я могу предоставлять пользовательские сообщения вместо ошибки, которая, вероятно, путает пользователей.
Существует ли какое-либо заметное увеличение производительности при использовании ограничений для триггеров и каковы наилучшие методы определения того, что использовать.
Ответы
Ответ 1
Ограничения снижаются!
-
С ограничениями вы указываете реляционные принципы, т.е. факты о ваших данных. Вам никогда не придется менять свои ограничения, если не произойдет какой-либо факт (т.е. Новые требования).
-
С триггерами вы указываете, как обрабатывать данные (вставки, обновления и т.д.). Это "нереляционный" способ делать вещи.
Чтобы лучше объяснить себя аналогией: правильный способ написать SQL-запрос - указать "что вы хотите" вместо "как его получить" – пусть RDBMS выяснит лучший способ сделать это за вас. То же самое применимо и здесь: если вы используете триггеры, вы должны иметь в виду различные вещи, такие как порядок выполнения, каскадирование и т.д. Пусть SQL сделает это для вас с ограничениями, если это возможно.
Это не означает, что триггеры не используют. Они делают: иногда вы не можете использовать ограничение, чтобы указать какой-то факт о ваших данных. Это очень редко. Если это случается с вами много, то, вероятно, есть проблема со схемой.
Ответ 2
Лучшая практика. Если вы можете сделать это с ограничением, используйте ограничение.
Триггеры не так плохи, как они получают дискредитацию (если они используются правильно), хотя я всегда буду использовать ограничение, когда это возможно. В современной RDMS накладные расходы на триггеры сопоставимы с ограничениями (конечно, это не означает, что кто-то не может помещать ужасный код в триггер!).
Иногда необходимо использовать триггер для принудительного применения "сложного" ограничения, такого как ситуация, требующая принудительного применения этого и только одного из полей внешнего ключа в таблице 2 (я видел эту ситуацию в нескольких доменах моделей).
Дискуссия о том, должна ли бизнес-логика находиться в приложении, а не в БД, в какой-то степени зависит от окружающей среды; если у вас много приложений, обращающихся к БД, как ограничения, так и триггеры могут служить окончательной защитой, что данные верны.
Ответ 3
В дополнение к другим причинам использования ограничений оптимизатор Oracle может использовать для этого преимущества.
Например, если у вас есть ограничение, говорящее (Amount >= 0)
, а затем вы запрашиваете с помощью WHERE (Amount = -5)
, Oracle сразу узнает, что нет соответствующих строк.
Ответ 4
Триггеры могут расцвести в проблему производительности. Примерно в это же время они также стали кошмаром для обслуживания. Вы не можете понять, что происходит и (бонус!), Приложение ведет себя беспорядочно с "ложными" проблемами с данными. [Действительно, это триггерные проблемы.]
Никакой конечный пользователь напрямую не затрагивает SQL. Они используют прикладные программы. Прикладные программы содержат бизнес-логику гораздо умнее и удобнее, чем триггеры. Поместите логику приложения в прикладные программы. Поместите данные в базу данных.
Если вы и ваши "пользователи" не используете общий язык, вы можете объяснить им нарушения ограничений. Альтернатива - не объясняя - превращает простую базу данных в проблему, потому что она объединяет данные и код приложения в недостижимую трясину.
"Как я могу получить абсолютную уверенность в том, что все, кто использует модель данных правильно?"
Два (полтора) метода.
-
Убедитесь, что модель справа: она соответствует домену проблем реального мира. Нет хаков или обходных путей или ярлыков, которые могут быть отсортированы только с помощью сложных пояснений, хранимых процедур и триггеров.
-
Помогите определить уровень бизнес-модели приложений. Уровень кода приложения, который все разделяют и используют повторно.
а. Кроме того, убедитесь, что слой модели отвечает потребностям людей. Если модельный слой имеет правильные методы и коллекции, меньше стимулов для обхода его, чтобы получить прямой доступ к базовым данным. Как правило, если модель правильная, это не вызывает глубокой озабоченности.
Триггеры - это крушение поезда, ожидающее своего служения. Ограничений нет.
Ответ 5
В общем, я бы предпочел ограничения, и мой код поймал бы ошибки sql-сервера и предоставил бы пользователю что-то более дружелюбное.
Ответ 6
Ограничения и триггеры для двух разных вещей. Ограничения используются для ограничения домена (действительные входы) ваших данных. Например, SSN будет храниться как char (9), но с ограничением [0-9] [0-9] [0-9] [0-9] [0-9] [0-9 ] [0-9] [0-9] [0-9] (все числовые).
Триггеры - это способ обеспечения бизнес-логики в вашей базе данных. Повторное использование SSN, возможно, контрольный журнал должен поддерживаться всякий раз, когда SSN изменяется - это будет сделано с помощью триггера,
В целом проблемы с целостностью данных в современной СУБД могут быть обработаны с некоторым изменением ограничения. Тем не менее, вы иногда попадаете в ситуацию, когда неправильная нормализация (или изменение требований, приводящая к неправильной нормализации) предотвращает ограничение. В этом случае триггер может укрепить ваше ограничение - но он непрозрачен для СУБД, то есть он не может использоваться для оптимизации. Это также "скрытая" логика и может быть проблемой обслуживания. Решение о том, следует ли реорганизовать схему или использовать триггер, является решением суда в этой точке.
Ответ 7
@onedaywhen
У вас может быть запрос как ограничение в SQL Server, вам просто нужно поместить его в скалярную функцию: http://www.eggheadcafe.com/software/aspnet/30056435/check-contraints-and-tsql.aspx
Ответ 8
Если это возможно, используйте ограничения. Они, как правило, слабее быстрее. Триггеры должны использоваться для сложной логики, которую ограничение не может обрабатывать. Запись триггеров тоже сложна, и если вы обнаружите, что должны написать триггер, убедитесь, что вы используете инструкции на основе набора, потому что тригеры работают против всей вставки, обновления или удаления (да, будут случаи, когда затронуто более одной записи, планируют на этом!), а не только по одной записи за раз. Не используйте курсор в триггере, если его можно избежать.
До того, как поставить логику в приложении вместо триггера или ограничения. НЕ ДЕЛАЙ ЭТОГО!!! Да, приложения должны иметь проверки перед отправкой данных, но целостность данных и бизнес-логика должны быть на уровне базы данных, или ваши данные будут перепутаны, когда к нему подключатся несколько приложений, когда глобальные вставки выполняются отдельно от приложения и т.д. Данные целостность является ключом к базам данных и должна выполняться на уровне базы данных.
Ответ 9
@Mark Brackett: "Ограничения используются для ограничения домена... Триггеры - это способ обеспечения бизнес-логики": это не так просто в SQL Server, потому что его ограничения ограничены, например. еще не полный SQL-92. Возьмем классический пример секвенциального "первичного ключа" во временной таблице базы данных: в идеале я бы использовал ограничение CHECK с подзапросом, чтобы предотвратить перекрывающиеся периоды для одного и того же объекта, но SQL Server не может этого сделать, поэтому я должен использовать вызывать. Также отсутствующим в SQL Server является способность SQL-92 отложить проверку ограничений, но вместо этого они (по сути) проверены после каждого оператора SQL, поэтому для работы с ограничениями SQL Server может потребоваться триггер.
Ответ 10
@Meff: есть потенциальные проблемы с подходом к использованию функции, потому что, просто говоря, ограничения SQL CHECK были сконструированы с одной строкой в качестве единицы работы и имеют недостатки при работе с набором результатов. Более подробную информацию об этом см. В: [http://blogs.conchango.com/davidportas/archive/2007/02/19/Trouble-with-CHECK-Constraints.aspx][1].
[1]: Блог Дэвида Портаса: проблема с ограничениями CHECK.
Ответ 11
То же, что и Skliwz.
Чтобы сообщить вам о каноническом использовании триггера, это таблица аудита. Если многие процедуры обновляют/вставляют/удаляют таблицу, которую вы хотите проверить (кто изменил, что и когда), триггер - это самый простой способ сделать это. одним из способов является просто добавить флаг в вашу таблицу (активный/неактивный с некоторым ограничением unicity) и вставить что-то в таблицу аудита.
Другой способ, если вы хотите, чтобы таблица не хранила исторические данные, заключается в том, чтобы скопировать предыдущую строку в таблицу аудита...
У многих людей есть много способов сделать это. Но одно можно сказать наверняка, вам нужно будет выполнить вставку для каждого обновления/вставки/удаления в этой таблице
Чтобы избежать ввода вставки в десятках разных мест, вы можете использовать триггер.
Ответ 12
Я согласен со всеми здесь в отношении ограничений. Используйте их как можно больше.
Существует тенденция злоупотреблять триггерами, особенно с новыми разработчиками. Я видел ситуации, когда триггер запускает другой триггер, который запускает другой триггер, который повторяет первый триггер, создавая каскадный триггер, который связывает ваш сервер. Это неоптимальный пользователь триггеров: o)
При этом триггеры имеют свое место и должны использоваться, когда это необходимо. Они особенно хороши для отслеживания изменений в данных (как отметил Марк Брэкетт). Вам нужно ответить на вопрос "Где это имеет смысл поставить мою бизнес-логику"? Большую часть времени я думаю, что это принадлежит коду, но вы должны держать в нем открытый разум.