24.06.2021, 21:22 | #1 |
Moderator
|
EAV-модель и хэширование.
Столкнулся с задачей разработки чего-то, что напоминает о финансовых аналитиках в D365 (конкретно таблицы DimensionAttributeSet/DimensionAttributeSetItem).
Требуется во многие таблицы в разных частях системы засунуть ссылки на некоторый набор аттрибутов. (Табличка эдак полей из 5-6, в среднем на одну сущность вешается порядка 7-10 аттрибутов, но попадаются и вырожденные случаи с 1 аттрибутом или с 400-500). Моя первая идея состояла в том, чтобы сделать что-то типа клона таблицы DocuRef. Просто добавляем в табличку с аттрибутами refTable и refRecId и живем дальше. (Пожалуй добавлю - я прекрасно знаю о всех проблемах с моделью EAV. Но здесь она вполне применима, поскольку аттрибуты используются только для просмотра/редактирования пользователем и потом для экспорта в некую внешнюю систему. Запросов по этим данным точно не будет. Можно меня не аггитировать против EAV). Однако по некотором размышлении, я пришел к выводу что эдак табличка с аттрибутами будет очень уж пухнуть. Аттрибуты прикрепляются к многим записям и при этом еще и часто наследуются и копируются между объектами. Так что могу представить что за год табличка с аттрибутами запросто может вырасти эдак мегабайтов на 300-400. При этом в большинстве случаев, число комбинаций значений аттрибутов - конечное. Вероятно таких комбинаций будет порядка 5-7 тысяч и за год будет прибавляться от силы тысяча. Появилась идея сделать отдельную табличку, где у меня только два поля - RecId и Hash. Смысл таблички - отдельная уникальная комбинация аттрибутов и их значений. Все остальные таблицы на нее ссылаются по RecId. (То есть - примерно как это со стандартной таблицей DimensionAttributeSet работает). Когда пользователь просматривает/редактирует аттрибуты, это происходит во временной таблице, куда мы при открытии формы закачиваем релевантные данные из настоящей таблицы аттрибутов. Когда форма закрывается, мы закачиваем содержимое всех значимых полей всех записей на форме в memoryStream и потом рассчитываем из него hash. Если запись с тем же самым hashем нашлась, то мы ничего не записываем, а просто вешаем ссылку на уже существуюшую запись. Если запись не нашлась - создаем новую запись в табличке с комбинациями аттрибутов и потом записываем сами аттрибуты. Потом вешаем ссылочку на новую запись. Если все хорошо работает, то получаем автоматическое сжатие таблицы аттрибутов, поскольку для одинаковых комбинаций аттрибутов записи создаваться не будут. Возникает два вопроса:
|
|
24.06.2021, 22:34 | #2 |
Участник
|
Цитата:
Сообщение от fed
Появилась идея сделать отдельную табличку, где у меня только два поля - RecId и Hash. Смысл таблички - отдельная уникальная комбинация аттрибутов и их значений. Все остальные таблицы на нее ссылаются по RecId. (То есть - примерно как это со стандартной таблицей DimensionAttributeSet работает).
нужно было в некой таблице сделать ссылку на разные источники данных с разным набором уникальных полей + возможность восстановления, если вдруг данные пересоздадут. Решали так же через общую табличку с + поле hash + дополнительное поле (соль). Цитата:
Хэш функции Why? Они использовали md5(возвращает guid) из соображений удобства не более на сколько знаю Цитата:
Сообщение от fed
Судя по тому что в интернетах пишут, SpookyHash должно хватать, но меня в моем Химикотехнологическом институте вопросам хэширования не учили и я не уверен Приму в дар советы от людей с более программистским образованием .[*]Какова вероятность hash collision, когда для разных message генерируются одинаковые hash ? - генерили hash на основе текстового набора имени таблицы + упорядоченных значений полей(это позволяло при необходимости без проблем добавить новое поле) + соль (изначально пустое значение) - hash был указан как уникальный ключ - при возникновении ситуации нарушения уникальности ( try catch с исключением duplicateKey) значение соли меняли (банальный счетчик вроде) и повторяли. Как то так Последний раз редактировалось axm2017; 24.06.2021 в 22:49. |
|
|
За это сообщение автора поблагодарили: fed (5), EVGL (3). |
25.06.2021, 07:43 | #3 |
Участник
|
Цитата:
возвращает int. очень похоже, что внутри тупой CRC. Цитата:
для dfo365, который работает в облаке, выбрать самый менее нагружающий процессор. даже если этого не требуется задачей. |
|
25.06.2021, 09:48 | #4 |
Moderator
|
Цитата:
Сообщение от axm2017
Низкая (скорее RecId пересекутся имхо), но для надежности коллеги сделали так:
- генерили hash на основе текстового набора имени таблицы + упорядоченных значений полей(это позволяло при необходимости без проблем добавить новое поле) + соль (изначально пустое значение) - hash был указан как уникальный ключ - при возникновении ситуации нарушения уникальности ( try catch с исключением duplicateKey) значение соли меняли (банальный счетчик вроде) и повторяли. |
|
25.06.2021, 10:19 | #5 |
Участник
|
|
|
25.06.2021, 20:59 | #6 |
Участник
|
А надо ли "хвосты" включать в хеш, если их относительно мало?
Т.е. идея в том, что генерить хеш по первым 10 (50?) атрибутам. А если атрибутов больше, то заранее считать их уникальными. Без сравнения. И для этой цели как раз "соль" и добавлять
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
28.06.2021, 17:05 | #7 |
Участник
|
Тут недавно Майкрософт срочно менял SHA1 на SpookyHash. Вот статья https://cloudblogs.microsoft.com/dyn...elease-wave-2/
|
|
|
За это сообщение автора поблагодарили: Logger (3). |