2013-09-09 2 views
0

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

В какой-то момент мы попытаемся вставить пакет, например. 10 миллионов документов-строк, но мы хотим хранить данные только в том случае, если мы не нарушаем уникальное ограничение, какой подход будет быстрее/считается ok ..?

например

try { 
    //...try and insert the document 
} catch(MySQLIntegrityConstraintViolationException e) { 
    //..do nothing, since this is already stored in the database 
    //move on to the next one.. 
} 

или

//we try to find the document... 
if(!documentFound) { 
    //we did not find a document with this id, so we can safely insert it.. 
    //move on to the next one... 
} 

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

Боковой вопрос: будет ли ответ/результат (с точки зрения, например, скорости) таким же, как Mysql, по отношению к mongoDB?

+3

сделать тест уникальности исключительно в mysql. Если вы протестируете на PHP, тогда попробуйте вставить, вы откроете условие гонки, когда какой-то другой экземпляр того же скрипта может бекаснуть этот слот db за спиной вашего скрипта.Конечно, вы всегда можете использовать блокировки таблиц/строк на уровне SQL, чтобы предотвратить это, но они открывают другие проблемы. –

+0

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

+0

Я не эксперт mysql, но я не думаю, что 'MySQLIntegrityConstraintViolationException' вызывается только тогда, когда у вас есть повторяющаяся запись, что означает, что это гораздо более безопасное решение. – user902383

ответ

2

Можете ли вы не просто использовать INSERT .. ON DUPLICATE. Таким образом, вам не нужно беспокоиться, если они уже существуют? Так что в вашем случае вы можете сделать

ON DUPLICATE KEY UPDATE id=id 
1

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

ПСЕВДОКОД

  1. Создать hashlist
  2. Поиск уникального ключа в хеш-листе
  3. Вставить в базу данных, если не найдено. Добавить уникальный ключ к хеш-листу
  4. 0 Следующая запись:
  5. Goto 2 if not eof.

Если у вас есть много дубликатов, вы сэкономите много (относительно) дорогих обращений к базе данных.

2

В целом, я бы выделил исключения для ... исключительных случаев :) Другими словами, если что-то может произойти в обычном рабочем процессе, я бы скорее обработал случай с помощью обычного if. Пустое предложение catch обычно предполагает, что что-то не так.

Кроме того, я предпочел бы использовать конструкцию INSERT IGNORE (вместо ON DUPLICATE - он работает нормально, но мне не нравится хакерский UPDATE id=id).

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

+0

ОК, но если нам интересно узнать, хорошо ли это вставить или плохой, это не будет работать в распределенной среде, если у нас будет несколько системных вставок, я думаю ?, поскольку мы должны использовать LAST_INSERT_ID(), чтобы определить, был ли счетчик увеличилось, и имея несколько систем, делающих вставки, мы не можем действительно полагаться на этот счетчик, я думаю? –

+0

'LAST_INSERT_ID()' возвращает идентификатор записи, вставленной ** в текущий сеанс ** (см. [Manual] (http://dev.mysql.com/doc/refman/5.6/en/information-functions.html # function_last-insert-id)), поэтому одновременные вставки не имеют значения. Кроме того, чтобы определить, удалось ли выполнить последний «INSERT IGNORE», я бы вместо этого проверил, было ли создано предупреждение («SHOW WARNINGS» или эквивалентный вызов API), но я думаю, что это действительно только вопрос вкуса. – RandomSeed