индекс по URL-адресу или хеширование с учетом ОЗУ

Я работаю над проектом, который должен ежедневно добавлять / обновлять около 1 миллиона URL-адресов. Некоторые дни в основном обновляются, некоторые дни в основном добавляются, а некоторые дни смешиваются.

Итак, по каждому запросу нужно искать уникальность url в таблице url.

Как поиск URL-адреса может быть сделан очень быстро, потому что на данный момент индекс установлен в столбце URL-адреса, и он работает хорошо, но в ближайшие недели ОЗУ будет недостаточно, если индекс будет храниться в том же столбце, и новые записи будут добавляться в миллионах.

Вот почему я ищу решение, чтобы, когда в общей сложности будет 150+ миллионов URL-адресов, его поиск должен быть быстрым. Я думаю о создании индексации на md5, но потом беспокоюсь о шансах столкновения. Друг посоветовал мне также вычислить хэш crc32 и объединить с md5, чтобы сделать возможность коллизии равной нулю и сохранить ее в двоичном формате (20), таким образом, только 20 байтов будут приняты как индекс вместо 255, в настоящее время varchar (255) установлен как данные столбца url тип.

В настоящее время существует около 50 миллионов URL-адресов, и с оперативной памятью 8 ГБ он работает нормально.

Вчера я задал вопрос сжатие текста URL (не сокращение) и хранение в mysql, относящееся к тому же проекту.

[Edit] Я придумал другое решение - поместить хэш crc32 только в десятичной форме, чтобы ускорить поиск. А при портировании на уровне приложения проверка количества возвращаемых записей. Если возвращается более 1 записи, также должен быть сопоставлен точный URL-адрес. Таким образом, столкновения также можно избежать, сохраняя при этом низкую нагрузку на оперативную память и дисковое пространство, сохраняя 4 байта для каждой строки вместо 20 байтов (md5 + crc32). Что вы скажете?


person Rick James    schedule 13.09.2011    source источник
comment
Если вы хешируете URL-адрес, это снизит производительность записи?   -  person ajreal    schedule 13.09.2011
comment
Это не большая проблема, потому что уникальный хэш URL-адреса может быть записан только один раз в жизни.   -  person Rick James    schedule 13.09.2011
comment
Босс, в своем вопросе вы указываете, что вам нужно добавлять / обновлять около 1 миллиона URL-адресов в день ... итак?   -  person ajreal    schedule 13.09.2011
comment
В обновлениях нет изменений в хэш-столбце, потому что это просто хэш URL-адреса, но обновляется несколько других столбцов в строке. Даже если будет больше новых добавлений, все равно будет не более 10 вставок в секунду в любое время.   -  person Rick James    schedule 13.09.2011
comment
Но вам нужно будет вычислить хеш для источника (как для вставки, так и для обновления), не так ли?   -  person ajreal    schedule 13.09.2011
comment
Если возможно, используйте для этого что-то вроде redis. Он будет работать быстрее, и 8 ГБ ОЗУ должно хватить. Кроме того, я думаю, что MD5 не должен вызывать беспокойства.   -  person Vikash    schedule 13.09.2011
comment
@Vikash Разве это не решение NoSQL? Хотя сейчас я настроен изучать что-то новое, потому что у меня есть время, но NoSQL - это совершенно новая территория, и я не хочу заманить в ловушку моего босса: p Если Redis может быстро искать хэши, то MySQL тоже может, потому что мои настройки не так уж и сложно попробовать нового быка. Но мне интересно узнать ваши взгляды на подробности о предпочтении Redis, а не индексировании хэшей в MySQL, или найти какое-либо другое решение с MySQL.   -  person Rick James    schedule 13.09.2011
comment
@ajreal Да, это будет вычисляться на уровне приложения, и это вообще повлияет на производительность записи .. как вы думаете, это снизит производительность записи?   -  person Rick James    schedule 13.09.2011


Ответы (1)


После прочтения всех ваших вопросов (уникальное ограничение делает хеши бесполезными?, 512-битный хэш против 4 128-битного хэша и сжатие текста url (не сокращение) и сохранение в mysql), я понял, что ваша проблема в большей или минус следующее:

"Мне нужно хранить 150 миллионов URL-адресов в mySQL, используя 8 ГБ ОЗУ, и при этом иметь хорошую производительность при их записи и извлечении, потому что я ежедневно обновляю их, поэтому я извлекаю много URL-адресов, проверяю их. против базы данных. На самом деле он имеет 50 миллионов URL-адресов и будет расти примерно на 1 миллион каждый день в следующие 3 месяца ".

Это оно?

Важны следующие моменты: Каков формат сохраняемого URL-адреса? Вам нужно будет прочитать URL-адрес или просто обновить информацию о нем, но никогда не выполнять поиск по частичным URL-адресам и т. Д.?

Предполагается, что URL = "http://www.somesite.com.tv/images/picture01.jpg "и что вы хотите сохранить все, включая имя файла. Если что-то не так, опишите подробнее или исправьте мои предположения об ответе.

  1. Если можно сэкономить место, заменив некоторую группу символов в URL-адресе. Не все символы ASCII допустимы в URL, как вы можете видеть здесь: RFC1738, так что вы можете использовать их для представления (и сжатия) URL-адреса. Например: использование символа 0x81 для представления «http: //» может заставить вас сохранить 6 символов, 0x82 для представления «.jpg» может сэкономить вам еще 3 байта и т. Д.

  2. Некоторые слова могут быть очень распространенными (например, «изображение», «изображение», «видео», «пользователь»). Если вы выберете пользовательские символы от 0x90 до 0x9f + любой другой символ (например, 0x90 0x01, 0x90 0x02, 0x90 0xfa) для кодирования таких слов, у вас может быть 16 * 256 = 4096 «словарных статей» для кодирования наиболее часто используемых слов. Вы будете использовать 2 байта для представления 4-8 символов.

Изменить: как вы можете прочитать в упомянутом выше RFC, в URL-адресе могут быть только печатаемые символы ASCII. Это означает, что следует использовать только символы от 0x20 до 0x7F, с некоторыми замечаниями, сделанными в RFC. Таким образом, не следует использовать любой символ после 0x80 (шестнадцатеричное представление, будет десятичным символом 128 в таблице ASCII). Итак, если можно выбрать один символ (скажем, 0x90) в качестве одного флага, чтобы указать, что «следующий байт является указанием в словаре, индексе, который я буду использовать». Один символ (0x90) * 256 символов (от 0x00 до 0xFF) = 256 записей в словаре. Но вы также можете использовать символы от 0x90 до 0x9f (или от 144 до 159 в десятичной системе), чтобы указать, что они являются флагом словаря, что дает вам 16 * 256 возможностей ...

Эти 2 метода могут сэкономить вам много места в вашей базе данных и являются обратимыми, без необходимости беспокоиться о коллизиях и т. Д. Вы просто создадите словарь в своем приложении и начнете кодировать / декодировать URL-адреса, используя его, очень быстро, делая ваша база данных намного легче.

Поскольку у вас уже есть более 50 миллионов URL-адресов, вы можете генерировать статистику на их основе, чтобы создать лучший словарь.

Использование хешей. В данном случае хеши представляют собой компромисс между размером и безопасностью. Насколько плохо будет, если вы попадете в столкновение? И в этом случае вы можете использовать парадокс дня рождения, чтобы помочь вам.

Прочтите статью, чтобы понять проблему: если бы все входные данные (возможные символы в URL-адресе) были эквивалентны, вы могли бы стимулировать вероятность столкновения. И мог бы вычислить обратное: учитывая вашу приемлемую вероятность столкновения и количество файлов, насколько широким должен быть ваш диапазон? И поскольку ваш диапазон точно связан с количеством бит, генерируемых хеш-функцией ...

Изменить: если у вас есть хеш-функция, которая дает вам 128 бит, у вас будет 2 ^ 128 возможных результатов. Итак, ваш «диапазон» в парадоксе дня рождения равен 2 ^ 128: это похоже на то, что в вашем году 2 ^ 128 дней вместо 365. Итак, вы вычисляете вероятность столкновения («два файла являются < em> родился в тот же день, с годом, в котором 2 ^ 128 дней вместо 365 дней). Если вы решите использовать хэш, который дает у вас 512 бит, ваш диапазон будет от 0 до 2 ^ 512 ...

И, опять же, помните о RFC: не все байты (256 символов) действительны в мире Интернета / URL. Таким образом, вероятность столкновений снижается. Для тебя лучше :).

person woliveirajr    schedule 15.09.2011
comment
Спасибо, что прочитали все мои вопросы. И да, вы поняли мою точку зрения, теперь было бы легко найти решение. Я уже проанализировал решение кодирования и декодирования, но я оставил его, потому что он будет работать только для английских слов, но наша база данных также содержит китайские символы, и многие URL-адреса имеют параметры с числами в качестве значений. Таким образом, это принесет нам меньшую ценность, чем вычисления, которые потребуются для отчетности. Вот почему я начал изучать хеши. Теперь я посмотрю еще раз, но что вы думаете об альтернативном решении (хэше или любом другом)? - person Rick James; 15.09.2011
comment
Более того, допустим, если будет достигнуто 50% -ное сжатие, даже тогда оно все равно будет выше диапазона 100 байт, в то время как 512-битный хэш займет только 64 байта. С другой стороны, varchar (255) для URL-адресов считается низким, и я также обнаружил много записей с усечением, поэтому, вероятно, этот предел скоро будет увеличен. - person Rick James; 15.09.2011
comment
Вы должны ответить / знать одно: если вы хешируете какой-то URL-адрес, вы не можете получить хеш и найти исходный URL-адрес. Если вам никогда не нужно этого делать, хорошо, хеши - это хорошо. Если вам нужно снова прочитать URL-адрес, вам нужно будет сохранить одну таблицу для связывания хеш-адреса ‹-› url. И это займет столько же места ... - person woliveirajr; 15.09.2011
comment
В конце концов, мы пришли к выводу, что для ускорения поисковых запросов мне нужно иметь дополнительное дисковое пространство, зарезервированное для хэшей, что не является большой проблемой. В то время как единогласное решение для быстрого поиска - использование хешей? - person Rick James; 15.09.2011
comment
Связано с вашим Edit - ›My Edit, о котором идет речь, относится к проверке исходного URL-адреса в случае коллизии и последующему изменению хэша на какое-то число. Это произойдет только в случае столкновения. Я думал, что перенос приложения проверки будет самым дешевым решением, теперь можно использовать даже небольшой хэш, чем 512 бит. Разве это не хороший компромисс? - person Rick James; 15.09.2011
comment
да, это так ... и это то, что в целом делает хеш-таблица :). Взгляните на en.wikipedia.org/wiki/Hash_table в разделе Разрешение конфликтов. - person woliveirajr; 15.09.2011
comment
Не могли бы вы уточнить значение фразы «А поскольку ваш диапазон точно связан с количеством бит, генерируемых хеш-функцией»? А какие пользовательские символы вы упомянули 0x90? И этот диапазон можно расширить? (хотя 4096 более чем достаточно :-)) - person Rick James; 15.09.2011
comment
Что ж, я нашел способ расширить диапазон, потому что коды символов undefined (стандарты HTML 4) html начинаются с 7F до 9F. ascii.cl/htmlcodes.htm - person Rick James; 15.09.2011