2014-01-31 2 views
1

У меня есть база данных с несколькими миллионами хэшей хэшей sha256. Я часто получаю миллионы новых файлов, которые я должен проверять на базе базы данных, чтобы избежать дублирования.Проверка миллионов файлов на миллионы хэшей для уже сохраненных файлов

Для проверки хэша файла с mysql db требуется много лет. Я уже разделил хэши на 16 таблиц (от 0 до F). Я уже пробовал couchbase, но для этого требуется более 8 ГБ моей оперативной памяти и прервал импорт с несколькими миллионами хэшей, оставив причину большого использования оперативной памяти ...

Может ли кто-нибудь дать мне решение для хранения около 4,5 ГБ хэши (размер calucalted, когда хеши выгружаются в текстовый файл) в базе данных, которая быстрее MySQL?

Хеши хранятся без какой-либо метаинформации, без имени файла или пути или идентификатора или чего-либо.

Уважения, 3vilc00kie

Редактировать Таблицы Определения:

-- phpMyAdmin SQL Dump 
-- version 3.3.9 
-- http://www.phpmyadmin.net 
-- 
-- Host: 127.0.0.1 
-- Erstellungszeit: 31. Januar 2014 um 13:55 
-- Server Version: 5.5.8 
-- PHP-Version: 5.3.5 

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 


/*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */; 
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */; 
/*!40101 SET @[email protected]@COLLATION_CONNECTION */; 
/*!40101 SET NAMES utf8 */; 

-- 
-- Datenbank: `filehashes` 
-- 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `0` 
-- 

CREATE TABLE IF NOT EXISTS `0` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `1` 
-- 

CREATE TABLE IF NOT EXISTS `1` (
    `sha256` binary(32) NOT NULL, 
    UNIQUE KEY `sha256` (`sha256`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `2` 
-- 

CREATE TABLE IF NOT EXISTS `2` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `3` 
-- 

CREATE TABLE IF NOT EXISTS `3` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `4` 
-- 

CREATE TABLE IF NOT EXISTS `4` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `5` 
-- 

CREATE TABLE IF NOT EXISTS `5` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `6` 
-- 

CREATE TABLE IF NOT EXISTS `6` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `7` 
-- 

CREATE TABLE IF NOT EXISTS `7` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `8` 
-- 

CREATE TABLE IF NOT EXISTS `8` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `9` 
-- 

CREATE TABLE IF NOT EXISTS `9` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `a` 
-- 

CREATE TABLE IF NOT EXISTS `a` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `b` 
-- 

CREATE TABLE IF NOT EXISTS `b` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `c` 
-- 

CREATE TABLE IF NOT EXISTS `c` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `d` 
-- 

CREATE TABLE IF NOT EXISTS `d` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `e` 
-- 

CREATE TABLE IF NOT EXISTS `e` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

-- -------------------------------------------------------- 

-- 
-- Tabellenstruktur für Tabelle `f` 
-- 

CREATE TABLE IF NOT EXISTS `f` (
    `sha256` binary(32) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 
+0

Разделение таблиц было, вероятно, контрпродуктивным. Проверка хеша не должна занимать «лет», если ваша таблица правильно проиндексирована по хеш-значению. Отправьте определение своей таблицы. – EJP

+0

Это не имеет смысла. Если вы указали хэш-столбец в db, проверка таблицы всего в несколько десятков миллионов должна быть близка к мгновенному. Расскажите нам больше, какой запрос вы выполняете, и как выглядит таблица (включая индексы). (То, что займет время в этом сценарии, фактически вычисляет хэш содержимого файла) – nos

+0

Черт, я только однажды использовал UNIQUE ... Это намного быстрее, когда я реализую его для всех таблиц? –

ответ

6

Возможно, вам не нужна база данных.

Sha256 имеет длину всего 32 байта. Я создал список из 50 миллионов уникальных sha256s, отсортировал их и поместил в файл (без кодировки шестнадцатеричного кодирования). Это 1,5 ГБ оперативной памяти для очень хорошо сбалансированной структуры сортировки двоичных файлов. Это должно быть достаточно легко для любого компьютера, который вы можете найти.

Итак, все, что вам нужно сделать, это прочитать или mmap его и выполнить двоичный поиск для каждого из них, который вы проверяете.

Когда база данных LinkedIn sha1s просочилась, появился сайт, который пытался сделать что-то похожее на то, что вы здесь делаете, помещая все хеши в сервер базы данных и позволяя пользователям проверять их из веб-запроса.

Это не работает надежно, поэтому я построил в основном то, что я описал выше. Если вы возьмете код в моем сущности здесь: https://gist.github.com/dustin/2885182 и измените для sha256 (в основном установите размеры хэша 32 вместо 20), он должен работать очень хорошо. Вы можете запустить логическую строку с файловым сканером для мгновенного поиска.

0

Вы можете использовать MySQL:

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

  • при использовании InnoDB, установите параметр innodb_buffer_pool_size конфигурации 50-80% доступной оперативной памяти: http://docs.oracle.com/cd/E17952_01/refman-5.5-en/innodb-configuration.html

  • , если вы не заботитесь, чтобы знать, что дубликаты, используйте REPLACE INTO ... VALUES (hash1), (hash2), ... для вставки 4000 или 10000 хэшей в то же время в одном заявлении. Поэкспериментируйте с тем, насколько важна объемная вставка, чтобы получить хороший баланс производительности.

+0

Я не вижу, как добавить ключ к ускорению. – EJP

+0

@EJP, потому что кланы innodb на первичном ключе и sha256 по дизайну неотличимы от случайных? http://stackoverflow.com/questions/9819271/why-is-mysql-innodb-insert-so-slow Я стараюсь сказать, что он хочет сравнить эти данные – Will

1

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

Но важно то, что важно. Создайте индекс для хеша mdx - это не должен быть первичным ключом или уникальным индексом. Если вы все сделаете правильно, то индекс будет единственным, загруженным в память.

Во-вторых, убедитесь, что MySQL настроен на использование большого количества памяти.

Если индекс вписывается в память, тогда вы в порядке.

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

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

0

Я думаю, что в вашем случае вы должны использовать HBASE и Redis.

Для хранения файлов вы можете использовать HBASE или Cassandra.

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

Вы можете использовать Redis для хранения хэша файлов.

У меня была возможность использовать Redis, и из моего опыта я могу сказать, что Redis - ад, быстро. Причина этого заключается в том, что REDIS - это хранилище данных в памяти.

This может помочь узнать больше о redis.

Таким образом, я думаю, вы должны использовать

Hbase/Cassandra: Хранить данные

Redis: Для хранения Hash.

Надеюсь, что это, возможно, помогло. Спасибо.

2

Просто добавьте индекс в поле «sha256». Фактически, как указывает Дастин, это всего лишь 1,5 ГБ данных. Он будет вписываться в одну таблицу в MySQL, если вам это нравится (и вы четко это понимаете). Просто указатель.

Смежные вопросы