Эффективный способ проверки строки большого числа, существующей в базе данных

У меня есть очень большая таблица в базе данных, в таблице есть столбец с именем "unique_code_string", эта таблица содержит почти 100 000 000 записей.

Каждые 2 минуты я буду получать 100 000 строк кода, они находятся в массиве и уникальны друг для друга. Мне нужно вставить их в большую таблицу, если они все «хорошие». Значение слова «хороший» следующее: Все 100 000 кодов в массиве никогда не встречаются в большой таблице базы данных.

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

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

Я думаю о других способах:

  1. Присоединяйтесь к коду 100 000 в предложении SQL "in", каждый код имеет длину 32, я думаю, что ни одна база данных не примет эту длину "in" 32 * 100 000.

  2. Используйте транзакцию базы данных, я все равно принудительно вставляю коды, если произойдет ошибка, откат транзакции. Это вызывает некоторые проблемы с производительностью.

  3. Используйте временную таблицу базы данных, я не умею писать SQL-запросы, пожалуйста, приведите мне пример, если эта идея может сработать.

Теперь, может ли кто-нибудь из экспертов дать мне несколько советов или какие-то решения?

Я не говорю по-английски, надеюсь, вы видите проблему, с которой я столкнулся.

Спасибо большое.

Не могли бы вы использовать вставку игнорирования SQL? mysqltutorial.org/mysql-вставка-игнорировать

J_C 10.04.2019 11:43

Инстинкт подскажет, что вариант 2 будет правильным. "Проблемы с производительностью" может возникнуть при работе с таким объемом данных, да, но я сомневаюсь, что какие-либо другие способы значительно улучшат это. Я не вижу, как тут может помочь временная таблица, к тому же с таким объемом данных это, вероятно, все равно будет означать, что данные все равно будут записываться на диск.

04FS 10.04.2019 11:45

@J_C Я не могу это использовать, потому что если какие-либо коды уже существуют в таблице базы данных, то весь этот массив (100 000 кодов) вообще не будет использоваться. Все равно спасибо :)

Hu Bin 10.04.2019 14:03
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Трудно найти оптимальное решение при таком малом количестве информации. Часто это зависит от сетевой задержки между приложением и сервером базы данных и аппаратными ресурсами.

  1. Вы можете загрузить 100 000 000 unique_code_string из базы данных и использовать HashSet или TreeSet для дедупликации в памяти перед вставкой в ​​базу данных. Если ваш сервер базы данных ограничен в ресурсах или существует значительная задержка в сети, это может быть быстрее.

  2. В зависимости от того, как вы получаете дельту из 100 000 записей, вы можете загрузить ее в базу данных, например. файл CSV можно прочитать с помощью внешняя таблица. Если вы можете эффективно получить данные во временную таблицу, а сервер базы данных не перегружен, вы можете сделать это очень эффективно с помощью SQL или хранимой процедуры.

Вы должны потратить некоторое время, чтобы понять, насколько в реальном времени должно быть обновление, например. сколько SQL-запросов считывает таблицу из 100 000 000 строк, и можете ли вы разрешить отмену или блокировку некоторых из этих SQL-запросов при обновлении строк. Часто хорошей идеей является создание теневой таблицы:

  • Создайте новую таблицу как копию существующей таблицы из 100 000 000 строк.
  • Отключить индексы в новой таблице
  • Загрузите дельта-строки в новую таблицу
  • Перестроить индексы в новой таблице
  • Удалить существующую таблицу
  • Переименуйте новую таблицу в существующую таблицу из 100 000 000 строк.

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

Я использовал этот метод раньше, я загрузил 100 000 000 в большой набор Java, так как они из базы данных bigtable, они уже уникальны! Но я все еще не могу избежать цикла 100 000, чтобы проверить каждый новый код, существующий в этом BigJavaSet.for(100,000 times) loop check BigJavaSet contains each code. Каждая проверка — это сравнение строк, и 100 000 раз занимают слишком много времени. Хуже всего то, что пока я не проверю все 100 000 кодов, я больше ничего не могу сделать.

Hu Bin 10.04.2019 14:42

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

Karol Dowbecki 10.04.2019 14:48
Ответ принят как подходящий

Загрузите 100 000 строк в таблицу!

Создайте уникальный индекс в исходной таблице:

create unique index unq_bigtable_uniquecodestring on bigtable (unique_code_string);

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

insert into bigtable ( . . . )
    select . . . 
    from smalltable;

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

insert into bigtable ( . . . )
    select . . . 
    from smalltable
    where not exists (select 1
                      from smalltable st join
                           bigtable bt
                           on st.unique_code_string = bt.unique_code_string
                      );

Для этой версии у вас также должно быть ограничение индекса/уникальности для smalltable(unique_code_string).

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