2009-02-16 3 views
4

Ключ к производительности: лучше ли каскадировать удаление/обновление внутри базы данных или позволить Hibernate/JPA позаботиться об этом?Каскадные удаления/обновления с использованием JPA или внутри базы данных?

Будет ли это возможность запрашивать данные, если каскады находятся внутри СУБД?

Я использую HSQLDB, если это имеет значение.

+0

У меня такая же проблема. До сих пор, похоже, никто не может действительно сказать, что такое корреляция между каскадами JPA/DB с точки зрения производительности. –

ответ

2

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

Пример: скажем, что у вас есть таблица поиска для штатов США с первичным ключом двухбуквенной аббревиатуры. Затем у вас есть таблица для почтовых адресов, которая ссылается на нее. Кто-то говорит вам, что вы ошибочно дали Монтане аббревиатуру «MO» вместо «MT», поэтому вам нужно изменить ее в таблице поиска.

CREATE TABLE States (st CHAR(2) PRIMARY KEY, state VARCHAR(20) NOT NULL); 
INSERT INTO States VALUES ('MO', 'Montana'); 

CREATE TABLE Addresses (addr VARCHAR(20), city VARCHAR(20), st CHAR(2), zip CHAR(6), 
    FOREIGN KEY (st) REFERENCES States(st)); 
INSERT INTO Addresses VALUES ('1301 East Sixth Ave.', 'Helena', 'MO', '59620'); 

Теперь вы исправите ошибку, не используя каскадные обновления на стороне базы данных. Ниже приведен тест с использованием MySQL 5.0 (предположим, что для Миссури нет записей, которые фактически используют аббревиатуру «MO»).

UPDATE States SET st = 'MT' WHERE st = 'MO'; 

ERROR 1451 (23000): Cannot delete or update a parent row: 
a foreign key constraint fails (`test/addresses`, 
CONSTRAINT `addresses_ibfk_1` FOREIGN KEY (`st`) REFERENCES `states` (`st`)) 

UPDATE Addresses SET st = 'MT' WHERE st = 'MO'; 

ERROR 1452 (23000): Cannot add or update a child row: 
a foreign key constraint fails (`test/addresses`, 
CONSTRAINT `addresses_ibfk_1` FOREIGN KEY (`st`) REFERENCES `states` (`st`)) 

UPDATE Addresses JOIN States USING (st) 
SET Addresses.st = 'MT', States.st = 'MT' 
WHERE States.st = 'MO'; 

ERROR 1451 (23000): Cannot delete or update a parent row: 
a foreign key constraint fails (`test/addresses`, 
CONSTRAINT `addresses_ibfk_1` FOREIGN KEY (`st`) REFERENCES `states` (`st`)) 

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

+0

Действительно? Как насчет этого: 'INSERT INTO State VALUES ('MT', 'Montana'); UPDATE Адреса SET st = 'MT' WHERE st = 'MO'; УДАЛИТЬ ОТ ГОСУДАРСТВ WHERE st = 'MO''. Вы можете утверждать, что это не так эффективно, как это делает RDBMS (это правда), но утверждать, что это невозможно в прикладном пространстве, просто неверно. –

+0

@JacekPrucia, вопрос был о каскадных обновлениях. Конечно, вы можете сделать это вручную в несколько шагов, и вы можете использовать транзакцию, чтобы сделать многоступенчатое изменение атомарным. Но преимущество использования каскадных обновлений заключается в том, что он автоматически находит 37 других таблиц, которые ссылаются на 'States', и обновляет их. Это было бы неудобно, если вы делаете это в нескольких заявлениях, как вы показываете, и если вы добавите 38-ю таблицу, вам придется изменить свой код. В то время как каскадные обновления неявно делают это. –

0
  1. Корректность является ключевой

Это говорит в данном случае корректности и производительность почти наверняка идет руку об руке с базы данных является правильным место для размещения (и соблюдения) жестких ограничений на целостности данных, и ее будет заметно быстрее серьезного удаления каскада поскольку оно:

  • Избегает несколько туда и обратно в базу данных
  • сокращает время, в течение которого сделка может иметь который будет проведен
  • Можно использовать внутренние структуры, связанные с внешнего ключа индекса, чтобы сделать это без тренировки/повторное использование некоторых план выполнения
0

UPDATE: выглядит подобный вопрос уже был дан ответ здесь When/Why to use Cascading in SQL Server?

IMO правильный ответ на ваш вопрос будет как обычно «все зависит». Если вы используете базу данных в качестве хранилища конфиденциальной информации (например, финансовой, медицинской и т. Д.), Или если у кого-то, кроме вашего приложения, может быть доступ к базе данных, я буду голосовать за подход Hibernate/JPA. Если ваша база данных предназначена для ведения журнала (например, трафик веб-сайта и т. Д.), Или если вы разрабатываете программное обеспечение со встроенной базой данных, вы можете относительно безопасно использовать каскадные операции.

2. В большинстве случаев я буду голосовать за подход Hibernate/JPA, потому что он более управляемый и предсказуемый.

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

+2

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

+0

«Удаленная одна строка, потерянная 30% базы данных» не является аргументом против каскадирования РСУБД, а скорее подтверждает, что этот конкретный администратор баз данных не был со своей структурой БД. Вы также пропустили основной аспект вопроса - «Производительность - это ключ», так как ничто в вашем ответе не связано с этим. Сопротивлялся соблазну ниспровергнуть хотя :) –

Смежные вопросы