Хэш фиксированной длины
Oct. 28th, 2011 06:01 amНесколько соображений, почему я использую концепцию key-value БД и хэши фиксированной длины как главные ключи.
Чисто архитектурно-программистское, кто не в теме, забейте.
Ну, для начала. Хэш фиксированной длины как сквозной уникальный идентификатор в базе гораздо удобнее, чем автоинкрементный ид. Выборка идёт с такой-же скоростью по хэшам, как по числовым идентификаторам – при этом “хороший” (типа md5) хэш обладает кучей всяких волшебных свойств…
Во-первых, хэши короткие. Если их передавать как параметр в урле, получается избежать чудовищных нагромождений в урлах. Собсно, сокращатели ссылок как раз считают хэши.
Во-вторых, по списку “хороших” хэшей никак не определить порядок, в котором они были созданы и не предсказать, какой хэш будет следующим. Скажем, по алгоритму bizwood.ru числа 1, 2 и 3 превратятся yxyhoe6a, zcpyd069 и xx9btfpz. А текст “Мама мыла раму” – в ktu4jmwf. Такой подход к идентификаторам упрощает некоторые аспекты обеспечения безопасности хранения и доступа.
Ещё полезняшка. Например, если вы храните древовидную структуру, и её надо время от времени обновлять или синхронизировать, нужно быстро определять, какие ветки изменились, а какие – нет. Для этого прекрасно подходят деревья Меркле – то-есть мы для всех используемых для сравнения веток считаем хэши и сравниваем их, а не ветки по значениям. Это в некоторых случаях (если листья длинные или деревья ветвистые) даёт огромный (порядки) выигрыш в производительности.
Деревья Меркле определённой разновидности позволяют организовывать очень быструю проверку прав доступа, шустрые лайки и счётчики доступа, быстрые бан-листы итп. Простейший вариант – таблица, клавный ключ которой – тупо конкат хэшей объекта и субъекта, а значение – права доступа. Или там лайк. Или счётчик.
Ещё прекрасное.
Хэши в силу того, что похожи на слова, прекрасно индексируются даже встроенными средствами полнотекстового индекса баз данных. Это вот что даёт.
Скажем, нам надо сделать сложную выборку записей определённого типа с определёнными тегами. Ещё записи должны быть созданы определённым пользователем или принадлежать определённой компании, к примеру.
Классический подход предполагает или тщательное проектирование БД с заточкой под такие запросы (для этого их с самого начала надо продумать все возможные), либо страшные джоины и низкую производительность. Ну и хреновую доступность из-за множества блокировок при записи в разные вспомогательные таблицы.
С хэшами можно иначе. Если у нас есть таблица, поддерживающая полнотекстовый поиск и содержащая в строках список всех хэшей, имеющих отношение к записи, перечисленных через пробел, задача становится тривиальной почти при любых мыслимых комбинаций отбора. Например, при использовании MyISAM-таблицы в MySQL-базе всё решается за 1 (один) SQL-запрос, содержащий MATCH AGAINST. И этот запрос – очень, очень быстрый.
Ну то-есть, когда мы пишем в базу обновление строчки, мы ещё пишем куда-то в соседнюю табличку перечисленные через пробел хэш типа, хэш создателя, хэши тегов записи и тд, всё что может пригодится. Например, на myhome29.ru пишется ещё хэш управляющей компании – если он есть, конечно. И хэш улицы. И города. А если надо будет, то и район будет писаться. И категория – типа деревянный, панельный или ещё какой – тоже хэшем соответствующего типа.
Таким манером, если в будущем возникнет какая-нибудь экзотика типа “найти все деревяшки какой-то УК по улице Пупкина” – это всё решится одним запросом, вполне стандартным.
Синонимические поисковые запросы тоже прекрасно решаются с помощью такого трюка. То-есть, мы пишем ещё и хэши всех синонимичных поисковых запросов в список. Или один хэш корневого запроса – тогда поиск удлиняется на целое обращение к базе по главному ключу.
Жаль, я поздно такой подход стал использовать. В бизвуде – половинчато. В myhome29 – уже в полный рост.
Какие-то идеи мне ещё наверное Redis даст, как это можно юзать.