@astrotrain

Какой самый быстрый способ проверить БД на вхождения множества строк?

Есть база, она в будущем будет довольно большая. Суть в том, что перед тем как процессить текстовый файл ~ 2мб нужно выбрать из него только те строки, которых нет в базе. Есть ли способ быстрее чем просто выбрать данные и построчно сравнить? Спасибо.
  • Вопрос задан
  • 171 просмотр
Пригласить эксперта
Ответы на вопрос 6
KarleKremen
@KarleKremen
Игнорирую Bootstrap
Насколько я знаю, запросы к мускулю и так идут по эффективному алгоритму. А так единственный адекватный вариант - брать строку и
SELECT `id` FROM `table` WHERE `field`="$наша_строка"
Ну и смотреть ответ
Ответ написан
@V_Tjuryakin
Перфекто
iCoderXXI
@iCoderXXI
React.JS/FrontEnd engineer
Текстовый файл 2 мб это не так много. Я бы спарсил текстовый файл в отдельную временную таблицу (даже можно in-memory), а потом от нее делал OUTER JOIN на основную, и в тех строках, которые есть в файле, но нет в основной таблице получил бы NULL, по которому и отбирал бы то, что надо дозалить в основную таблицу.

Это более-мене адекватный и производительный способ на мой взгляд.

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

Если же в строках что-то плавает, например регистр символов, то перед вычислением хэша строки надо приводить к единому виду. Причем в таблицах помимо хэшей хранить можно и оригинальные строки, тут вопрос только о вариантах сравнения.
Ответ написан
VladimirAndreev
@VladimirAndreev
php web dev
а строки целиком сохраняются в базу?
если да - я бы хранил md5 от строки (если, конечно, исходные строки не короче 32 символов), на это уникальный индекс и вперед.
Ответ написан
mahoho
@mahoho
Full stack certified PHP developer.
Если вы загружаете при помощи LOAD DATA INFILE, тогда используйте LOAD DATA INFILE 'file_name' IGNORE - дубликаты будут проигнорированы.
Если через INSERT со множеством VALUES, тогда можно также использовать INSERT IGNORE.
Однако оба варианта подразуемевают увеличение AUTO_INCREMENT поля целевой таблицы (если есть) при неудачной попытке записи дубликата.
Для избежания этой проблемы можно загружать во временную таблицу, а затем делать примерно так:
INSERT INTO target_table (field1, field2)
	SELECT field1, field2 FROM temporary_table WHERE not EXISTS(
		select 1 from target_table where temporary_table.id = target_table.id
	)
Ответ написан
winordie
@winordie
Лучшая документация -- исходники
У меня стояла подобная задача: надо было из файла добавлять данные, которых нет в базе. В файле было 4 000 000 записей и в базе столько же. Итого чтобы их пройти надо было совершить примерно 8*10^12 итераций.

Поэтому я одним запросом получал из базы все значения полей по которым шло сравнение с сортировкой по ним. Дальше проходил в цикле по всем записям из файла и бинарным поиском находил те которых нет в базе. Итого получалось не более 5*10^7 итераций и 1 запрос к базе чтобы найти записи из файла которых еще нет в базе.

Но у меня были числовые данные по которым легко бинарным поиском искать и сравнение шло только по 2 полям таблицы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы