• XSS.stack #1 – первый литературный журнал от юзеров форума

Алгоритмы сортировки и удаления дублей строк в больших TXT файлах объемом от 1ГБ

rand

CooL-Lamer
Эксперт
Регистрация
24.05.2023
Сообщения
581
Реакции
1 152
Депозит
0.07 Ł и др.
Всем привет, недавно наткнулся на интересный тред: https://xss.pro/threads/122300/
ТС же в нем очень перемудрил с алгоритмом на мой взгяд, но это не то что меня заинтересовало. Как реализовать такой функционал на C# (Знаю только Паскаль, Шарп, и Петухон☺️) мне понятно, а вот как сделать это быстро интерпретатором очень интересная задача, так что решил создать тред где буду размещать придуманные мной алгоритмы на ЯП этого раздела.
Продолжу этот тред здесь:
Больше 1gb к примеру. Что бы сортировать такие файлы одного .readlines() будет маловато.
Еще не понятно, что есть юзернеймы? Какой формат строк должен быть?
username? email:pass? разделитель?
Очень интересная задача для питона, я подумаю на досуге за алгоритм сортировки и удаления дублей в большом файле без критичного потребления ОЗУ. Всё что пока пришло на ум для быстрой очистки от дублей это применить функцию set (множества элементов) в списке, сгенерировал файл с дублями в объеме до 2 гигов (точный размер 1.84гб) такого вида:
1726667404719.png

В целом получилось чуть больше 108 миллионов строк, размер ОЗУ моей системы 32 гигабайта (в пике потребление по диспетчеру задач у скрипта в районе 12-14 гигабайт). На обработку скрипта ушло:
1726667447773.png


На выходе получилось как-то так:
1726667476247.png


main.py
Python:
import time

name_file = "bd_dublicate.txt" # Передаю имя исходного файла

tic = time.perf_counter() # Запускаем таймер и вычисляем время работы скрипта в секундах

# Чтение файла
with open(name_file, 'r', encoding='utf-8') as file:
    f = file.read()

# Разделение строк
total = f.split('\n')
# Удаление дубликатов
unique_lines = list(set(total))
#print(unique_lines)

# Подсчет удаленных строк
print(len(total) - len(unique_lines), 'всего удалённых строк')

# Запись уникальных строк в новый файл
with open("output.txt", 'w', encoding='utf-8') as output_file:
    output_file.write('\n'.join(unique_lines))
    print("Файл успешно сохранен.")
tac = time.perf_counter()
print(f"Удаление дублей заняло {tac - tic:0.4f} секунд")

У меня есть АП ULP и вариант им почистить его от дублей? 500гб вес... за*бался искаться софт для удаление дублей в ULP
Можно попробовать файл поделить на несколько частей, к примеру по 2 гигабайта, пройтись по ним алгоритмом выше в цикле, а потом объединить всё в один файл, но это в теории. Пока не имею возможности сгенерировать такой объем для проверки этой теории. Ну и также на границе смещения могут быть дубли при таком подходе.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Мне идея приходила диск юзать, читаешь файл стримом построчно, каждую строку преобразуешь в base64 и пишешь файл в папку использовав base64 названия строки, тем самым потребления озу вообще не будет, а ты можешь проверять файл по названию существует ли он, если существует то дубль
 
Удаление дублей по алгоритму указанному выше на размере файла 5.9гб (при работе скрипта выжирало всю свободную ОЗУ).
Структура файла (302 миллиона строк):
1726668651444.png

На выходе:
1726668697768.png

Время выполнения сильно увеличилось из-за нехватки ОЗУ:
1726668760792.png
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Удаление дублей по алгоритму указанному выше на размере файла 5.9гб (при работе скрипта выжирало всю свободную ОЗУ).
Структура файла (302 миллиона строк):
Посмотреть вложение 95171
На выходе:
Посмотреть вложение 95172
Время выполнения сильно увеличилось из-за нехватки ОЗУ:
Посмотреть вложение 95173
Мне моих 128 гб озу не хватало чтоб почистить дубли) по этоему единственное решение которое подойдет, это через диск что выше написал
 
Мне моих 128 гб озу не хватало чтоб почистить дубли) по этоему единственное решение которое подойдет, это через диск что выше написал
Интересная идея, есть код? И какой был размер файла? =)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Интересная идея, есть код? И какой был размер файла? =)
Я уже не помню, но я пыталься забить 4 тб, Кода нету, но его легко написать, там же агоритм простой
 
Я уже не помню, но я пыталься забить 4 тб, Кода нету, но его легко написать, там же агоритм простой
Ого, в таком случае очень высока нагрузка на ПЗУ, железку не жалко? =)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Ого, в таком случае очень высока нагрузка на ПЗУ, железку не жалко? =)
Я думаю ей пофиг
 
Мне идея приходила диск юзать, читаешь файл стримом построчно, каждую строку преобразуешь в base64 и пишешь файл в папку использовав base64 названия строки, тем самым потребления озу вообще не будет, а ты можешь проверять файл по названию существует ли он, если существует то дубль
Т.е. если в файле миллиард уникальных строк, то нужно создать миллиард файлов на диске ? NTFS может даже и вывезет такое изнасилование, но это точно не лучшее решение.

Если нужно только удалить дубли, а не отсортировать файл, то правильнее будет делать так
1. читаем строку из файла
2. подсчитываем для этой строки какой-нибудь криптографический хеш типа sha256 с околонулевой вероятностью коллизии
3. проверяем есть ли этот хеш в хеш-таблице. Если есть - значит это дубль-строка, если нет - добавляем хеш в хеш таблицу
Это решение тоже не идеальное, потому что о для реально гигантских текстовых файлов сама по себе lookup хеш таблица может не влезть в ОЗУ.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Т.е. если в файле миллиард уникальных строк, то нужно создать миллиард файлов на диске ? NTFS может даже и вывезет такое изнасилование, но это точно не лучшее решение.

Если нужно только удалить дубли, а не отсортировать файл, то правильнее будет делать так
1. читаем строку из файла
2. подсчитываем для этой строки какой-нибудь криптографический хеш типа sha256 с околонулевой вероятностью коллизии
3. проверяем есть ли этот хеш в хеш-таблице. Если есть - значит это дубль-строка, если нет - добавляем хеш в хеш таблицу
Это решение тоже не идеальное, потому что о для реально гигантских текстовых файлов сама по себе lookup хеш таблица может не влезть в ОЗУ.
А какая разница, он же пишет данные а не милиард дублей записывает, я думаю спокойно вывезет, ну бля если не нравится на диск писать пиши в базу данных, вот только база данных тоже на диске хранится. Так какая разница в бд записывать или на диск?
 
Т.е. если в файле миллиард уникальных строк, то нужно создать миллиард файлов на диске ? NTFS может даже и вывезет такое изнасилование, но это точно не лучшее решение.

Если нужно только удалить дубли, а не отсортировать файл, то правильнее будет делать так
1. читаем строку из файла
2. подсчитываем для этой строки какой-нибудь криптографический хеш типа sha256 с околонулевой вероятностью коллизии
3. проверяем есть ли этот хеш в хеш-таблице. Если есть - значит это дубль-строка, если нет - добавляем хеш в хеш таблицу
Это решение тоже не идеальное, потому что о для реально гигантских текстовых файлов сама по себе lookup хеш таблица может не влезть в ОЗУ.
Вариант с построчным чтением файла вместо записи всего файла в память. Что позволяет обрабатывать большие файлы без больших затрат ОЗУ.
На примере того шестигигового варианта выше:
Python:
import time

name_file = "bd_dublicate.txt"

tic = time.perf_counter()

unique_lines = set()  # Храним уникальные строки

with open(name_file, 'r', encoding='utf-8') as file, open("output.txt", 'w', encoding='utf-8') as output_file:
    removed_count = 0  # Счетчик удалённых строк
    for line in file: # # Проходим по каждой строке файла
        if line not in unique_lines:
            output_file.write(line)  # Записываем уникальные строки сразу
            unique_lines.add(line) # Добавляем строку в множество уникальных строк
        else:
            removed_count += 1  # Увеличиваем счетчик дубликатов

print(f'{removed_count} всего удалённых строк')

tac = time.perf_counter()
print(f"Удаление дублей заняло {tac - tic:0.4f} секунд")

1726670601402.png
 
Последнее редактирование:
Код:
PS C:\> python double.py
Traceback (most recent call last):
  File "C:\double.py", line 11, in <module>
    for line in file:
                ^^^^
  File "<frozen codecs>", line 322, in decode
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 5248-5249: invalid continuation byte

можно как то игнорировать ошибки кодировки, либо сразу удалять такие строки?
 
Код:
PS C:\> python double.py
Traceback (most recent call last):
  File "C:\double.py", line 11, in <module>
    for line in file:
                ^^^^
  File "<frozen codecs>", line 322, in decode
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 5248-5249: invalid continuation byte

можно как то игнорировать ошибки кодировки, либо сразу удалять такие строки?
Не пробовал удалять аргумент кодировки при открытии файла?
 
unique_lines.add(line)
На этой строчке ты все равно загружаешь все уникальные строки из файла в ОЗУ. Т.е. да, ты файл читаешь построчно, а не целиком, но это все равно не помогает от того, что большая часть строк из файла таки будут в ОЗУ
 
На этой строчке ты все равно загружаешь все уникальные строки из файла в ОЗУ. Т.е. да, ты файл читаешь построчно, а не целиком, но это все равно не помогает от того, что большая часть строк из файла таки будут в ОЗУ
Ну да, такой метод работает если дублей очень много =)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
вообще попробуй переписать чтоб ты сверял реально по базе, самая оптимальное что наверное могу посоветовать и без установки доп бд и всяких пакетов это sqlite и лимиты вроде позволяют https://www.sqlite.org/limits.html
1726671679073.png
 
Пожалуйста, обратите внимание, что пользователь заблокирован
вообще попробуй переписать чтоб ты сверял реально по базе, самая оптимальное что наверное могу посоветовать и без установки доп бд и всяких пакетов это sqlite и лимиты вроде позволяют https://www.sqlite.org/limits.html
Посмотреть вложение 95179
Максимальный размер файла базы данных: По умолчанию 140 терабайт (ТБ), но это может быть увеличено, если используется нестандартная сборка SQLite.
 
Код:
PS C:\> python double.py
Traceback (most recent call last):
  File "C:\double.py", line 11, in <module>
    for line in file:
                ^^^^
  File "<frozen codecs>", line 322, in decode
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 5248-5249: invalid continuation byte

можно как то игнорировать ошибки кодировки, либо сразу удалять такие строки?
изменил на
Код:
with open(name_file, 'r', encoding='utf-8', errors='ignore')
и вроде завелось
 
Спасибо кто отписался выше, попробую на досуге реализовать те варианты решений про которые написали.
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх