Лучший способ проверить наличие дубликатов ключей в базе данных

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

  •  05-07-2019
  •  | 
  •  

Вопрос

Это скорее вопрос корректности.Допустим, у меня есть таблица со столбцом первичного ключа в моей базе данных.В моем коде DAO у меня есть функция под названием InsertRow(строковый ключ), которая возвращает true, если ключ не существует в таблице, и вставляет новую строку с этим ключом.В противном случае, если строка с этим ключом уже существует, она возвращает false.Лучше/хуже сначала проверить InsertRow на наличие ключа или просто выполнить вставку и обнаружить ошибку дублирующегося ключа?Или экономия на одном операторе выбора — это слишком тривиальная оптимизация, чтобы о ней даже беспокоиться?

Итак, в коде sudo:

boolean insertRow(String key){
    //potentially a select + insert
    if(select count(*) from mytable where key = "somekey" == 0){
       insert into mytable values("somekey")
       return true;
    }
    return false;
}

или

  boolean insertRow(String key){
    try{
       //always just 1 insert
       insert into mytable values("somekey")
       return true;
    } catch (DuplicateKeyException ex){}
    return false;
  }
Это было полезно?

Решение

Попробуй вставку, потом поймай ошибку.

В противном случае вы могли бы все еще есть проблема параллелизма между двумя активными SPID (скажем, двумя веб-пользователями в системе одновременно), и в этом случае вам все равно придется отловить ошибку:

User1: Check for key "newkey"? Not in database.
User2: Check for key "newkey"? Not in database.
User1: Insert key "newkey". Success.
User2: Insert key "newkey". Duplicate Key Error.

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

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

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

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

Только протестировав оба сценария, вы узнаете наверняка.

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

Если целью кода является обновление, вам следует использовать выбор или INSERT ... ON DUPLICATE KEY UPDATE (если это поддерживается вашим механизмом базы данных.) Альтернативно создайте хранимую процедуру, которая будет обрабатывать эту логику за вас.

Второй, потому что первый вариант попадает в два раза больше БД, а второй - только один раз.

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

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

Однако я бы предложил использовать EXISTS запрос, а не count(*)

if(exists (select 1 from mytable where key = "somekey"))
    return false
else
    insert the row

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

Другой вариант — полностью поместить логику в оператор SQL.

еще два варианта в MySQL — использовать

insert ignore into....

и

insert into .... on duplicate key update field=value

включая on duplicate key update field=field

Видеть: http://dev.mysql.com/doc/refman/5.0/en/insert.html

Редактировать:Вы можете проверить effect_rows на предмет того, оказала ли вставка эффект или нет.

Теперь, когда я нашел в Интернете книгу Мартина Фаулера, достойный способ сделать это — использовать ключевой стол- дополнительную информацию см. на стр. 222.

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