У меня есть очень большая таблица в базе данных, в таблице есть столбец с именем "unique_code_string", эта таблица содержит почти 100 000 000 записей.
Каждые 2 минуты я буду получать 100 000 строк кода, они находятся в массиве и уникальны друг для друга. Мне нужно вставить их в большую таблицу, если они все «хорошие». Значение слова «хороший» следующее: Все 100 000 кодов в массиве никогда не встречаются в большой таблице базы данных.
Если один или несколько кодов встречаются в большой таблице базы данных, весь массив вообще не будет использоваться, это означает, что никакие коды в массиве не будут вставлены в большую таблицу.
В настоящее время я использую этот способ: Сначала я делаю цикл и проверяю каждый код в массиве, чтобы увидеть, есть ли уже такой же код в большой таблице базы данных. Во-вторых, если весь код "новый", то я делаю настоящую вставку. Но этот способ очень медленный, я должен закончить все за 2 минуты.
Я думаю о других способах:
Присоединяйтесь к коду 100 000 в предложении SQL "in", каждый код имеет длину 32, я думаю, что ни одна база данных не примет эту длину "in" 32 * 100 000.
Используйте транзакцию базы данных, я все равно принудительно вставляю коды, если произойдет ошибка, откат транзакции. Это вызывает некоторые проблемы с производительностью.
Используйте временную таблицу базы данных, я не умею писать SQL-запросы, пожалуйста, приведите мне пример, если эта идея может сработать.
Теперь, может ли кто-нибудь из экспертов дать мне несколько советов или какие-то решения?
Я не говорю по-английски, надеюсь, вы видите проблему, с которой я столкнулся.
Спасибо большое.
Инстинкт подскажет, что вариант 2 будет правильным. "Проблемы с производительностью" может возникнуть при работе с таким объемом данных, да, но я сомневаюсь, что какие-либо другие способы значительно улучшат это. Я не вижу, как тут может помочь временная таблица, к тому же с таким объемом данных это, вероятно, все равно будет означать, что данные все равно будут записываться на диск.
@J_C Я не могу это использовать, потому что если какие-либо коды уже существуют в таблице базы данных, то весь этот массив (100 000 кодов) вообще не будет использоваться. Все равно спасибо :)
Трудно найти оптимальное решение при таком малом количестве информации. Часто это зависит от сетевой задержки между приложением и сервером базы данных и аппаратными ресурсами.
Вы можете загрузить 100 000 000 unique_code_string
из базы данных и использовать HashSet
или TreeSet
для дедупликации в памяти перед вставкой в базу данных. Если ваш сервер базы данных ограничен в ресурсах или существует значительная задержка в сети, это может быть быстрее.
В зависимости от того, как вы получаете дельту из 100 000 записей, вы можете загрузить ее в базу данных, например. файл CSV можно прочитать с помощью внешняя таблица. Если вы можете эффективно получить данные во временную таблицу, а сервер базы данных не перегружен, вы можете сделать это очень эффективно с помощью SQL или хранимой процедуры.
Вы должны потратить некоторое время, чтобы понять, насколько в реальном времени должно быть обновление, например. сколько SQL-запросов считывает таблицу из 100 000 000 строк, и можете ли вы разрешить отмену или блокировку некоторых из этих SQL-запросов при обновлении строк. Часто хорошей идеей является создание теневой таблицы:
Подход здесь специфичен для базы данных. Это будет зависеть от того, как ваша база данных определяет индексы, например. если у вас есть секционированная таблица, возможно, в этом нет необходимости.
Я использовал этот метод раньше, я загрузил 100 000 000 в большой набор Java, так как они из базы данных bigtable, они уже уникальны! Но я все еще не могу избежать цикла 100 000, чтобы проверить каждый новый код, существующий в этом BigJavaSet.for(100,000 times) loop check BigJavaSet contains each code
. Каждая проверка — это сравнение строк, и 100 000 раз занимают слишком много времени. Хуже всего то, что пока я не проверю все 100 000 кодов, я больше ничего не могу сделать.
Вы можете улучшить это, используя несколько потоков для параллельного сравнения. Так или иначе, если это случайные строки, вам всегда придется выполнять 100 000 сравнений, даже когда вы загружаете их в базу данных, SQL-движок сделает это.
Загрузите 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)
.
Не могли бы вы использовать вставку игнорирования SQL? mysqltutorial.org/mysql-вставка-игнорировать