Должен ли я применять бизнес-логику через ошибки базы данных? - PullRequest
1 голос
/ 18 февраля 2011

Есть интересное дизайнерское решение, о котором я думал в последнее время. Допустим, я добавляю имена пользователей в таблицу и хочу убедиться в отсутствии дубликатов. Столбец имени пользователя NOT NULL UNIQUE. Я мог бы либо:

  1. Запросите базу данных перед вставкой, чтобы убедиться, что нет повторяющихся имен, или
  2. Просто INSERT и перехватывайте любые исключения, поступающие от ядра базы данных.

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

Ответы [ 3 ]

1 голос
/ 18 февраля 2011

Почти всегда кажется хорошей идеей сделать вариант 2. Я бы не рекомендовал вариант 1, потому что вы фактически удвоили количество времени, необходимое для выполнения вставок (все они сначала требуют чтения). Кроме того, какой-то новый разработчик собирается просто фиксировать время, а не проверять, и он сломается.

Еще одна вещь, которую следует учитывать, это то, сколько времени простоя уместно? Это критически важное приложение? Что произойдет, если бизнес-логика повреждена? Завершат ли заводы, если это так? Или это будут просто неприятные ошибки.

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

1 голос
/ 18 февраля 2011

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

0 голосов
/ 18 февраля 2011

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

Быстрая демонстрация (в Oracle 11.2.0.1) показывает, что примерно в 7 раз дороже выполнить неудачную вставку и обработать исключение, чем проверка перед вставкой, а затем запись данных.

SQL> create table username_test (
  2    username varchar2(30) unique
  3  );

Table created.

SQL> set timing on;

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_cnt integer;
  3  begin
  4    for i in 1 .. 100000
  5    loop
  6      select count(*)
  7        into l_cnt
  8        from username_test
  9       where username = 'JCAVE';
 10      if( l_cnt = 0 )
 11      then
 12        insert into username_test( username )
 13          values( 'JCAVE' );
 14      end if;
 15    end loop;
 16* end;
SQL> /

PL/SQL procedure successfully completed.

Elapsed: 00:00:04.20
SQL> rollback;

Rollback complete.

Elapsed: 00:00:00.00

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_cnt integer;
  3  begin
  4    for i in 1 .. 100000
  5    loop
  6      begin
  7       insert into username_test( username )
  8          values( 'JCAVE' );
  9      exception
 10        when dup_val_on_index then
 11          null;
 12      end;
 13    end loop;
 14* end;
SQL> /

PL/SQL procedure successfully completed.

Elapsed: 00:00:29.58
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...