Сделать уникальный идентификатор для записи
От: .alex Ниоткуда  
Дата: 29.04.19 05:42
Оценка:
Добрый день. У меня задача сделать уникальный идентификатор записи в бд. Т.е. имеется очень много файлов, в имени файла есть три даты: начало и конец периода и дата создания (но вместе с тем, уникальность имени не гарантирована). Данные из этих файлов загружаются моей программой в таблицу бд. Записей может быть больше 20 млрд.
Идея есть такая. Посчитать crc32 по строке имя файла + размер файла. Затем из четырёх байт crc32 сделать 3, например помножив 0 и 1 байт crc32, эти 3 байта сделать старшими в unsigned long long int моего идентификатора, ну а нижние 5 байтов использовать как место для счетчика порядкового номера записи каждого файла...
Вопрос собственно в том, здраво ли это звучит и как именно установить 3 старший байта и потом инкриминировать 5 нижних отдельно от всех 8 байт...
надеюсь сформулировал понятно...)
Re: Сделать уникальный идентификатор для записи
От: kov_serg Россия  
Дата: 29.04.19 06:27
Оценка:
Здравствуйте, .alex, Вы писали:

A>Добрый день. У меня задача сделать уникальный идентификатор записи в бд.

Уникальный идентификатор в бд может создавать сама бд.
А если надо привязать к содержимому файла то чем обычные hash-ы не угодили md5,sha1,sha256,...

A>Т.е. имеется очень много файлов, в имени файла есть три даты: начало и конец периода и дата создания (но вместе с тем, уникальность имени не гарантирована). Данные из этих файлов загружаются моей программой в таблицу бд. Записей может быть больше 20 млрд.

A>Идея есть такая.
A>Посчитать crc32 по строке имя файла + размер файла.
если вы добавите к любому файлу crc32 и потом заново посчитаете crc32 то вы удивитесь.

A>Затем из четырёх байт crc32 сделать 3, например помножив 0 и 1 байт crc32, эти 3 байта сделать старшими в unsigned long long int моего идентификатора, ну а нижние 5 байтов использовать как место для счетчика порядкового номера записи каждого файла...

A>Вопрос собственно в том, здраво ли это звучит и как именно установить 3 старший байта и потом инкриминировать 5 нижних отдельно от всех 8 байт...
A>надеюсь сформулировал понятно...)
Для 20млрд записай база будет под терабайт.
Re[2]: Сделать уникальный идентификатор для записи
От: .alex Ниоткуда  
Дата: 29.04.19 20:06
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Уникальный идентификатор в бд может создавать сама бд.

Средствами БД ([UID] [bigint] IDENTITY(1,1) NOT NULL) не подходит... Гружу в таблицу через oledb интерфейс IRowSetFastLoad в 12 потоков (сразу 12 файлов) и если использовать автоинкрементное поле, скорость загрузки падает с 5-7ГБ/мин до 1,2ГБ/мин, что неприемлемо....

_>А если надо привязать к содержимому файла то чем обычные hash-ы не угодили md5,sha1,sha256,...

_>если вы добавите к любому файлу crc32 и потом заново посчитаете crc32 то вы удивитесь.
это понятно, удивляться не буду) наверно я не совсем понятно выразился. мне не нужно считать какой-либо хэш по самому файлу, идея была в том чтобы сделать максимально уникальную строку, например из имени файла и его размера (размер + имя уникально в наборе загружаемых файлов) и по этой строке посчитать самый быстрый и маленький (по размеру) хэш (думаю crc32 самый подходящий), а потом использовать полученный хэш как часть уникального идентификатора, а вторая часть была бы просто порядковым номером записи в конкретном файле...

_>Для 20млрд записай база будет под терабайт.

да не просто ТБ, а несколько ТБ — 5-6... это как бы тоже понятно)

В принципе вот так вроде работает...
unsigned long long int uid = crc32c(0, (const unsigned char*)sStr2Crc32.c_str(), sStr2Crc32.size());
BYTE* p = (BYTE*)& uid;
p[7] = p[3];
p[6] = p[2];
p[5] = p[0] * p[1];
uid &= 0xFFFFFFFF00000000;
uid++;
...

Теперь 3 старших байта unsigned long long int содержат crc32 (чуть урезанную)), а 5 младших счетчик...
Отредактировано 29.04.2019 20:33 .alex . Предыдущая версия .
Re[3]: Сделать уникальный идентификатор для записи
От: ffk  
Дата: 30.04.19 07:44
Оценка:
Здравствуйте, .alex, Вы писали:

A>Здравствуйте, kov_serg, Вы писали:


_>>Уникальный идентификатор в бд может создавать сама бд.

A>Средствами БД ([UID] [bigint] IDENTITY(1,1) NOT NULL) не подходит... Гружу в таблицу через oledb интерфейс IRowSetFastLoad в 12 потоков (сразу 12 файлов) и если использовать автоинкрементное поле, скорость загрузки падает с 5-7ГБ/мин до 1,2ГБ/мин, что неприемлемо....

_>>А если надо привязать к содержимому файла то чем обычные hash-ы не угодили md5,sha1,sha256,...

_>>если вы добавите к любому файлу crc32 и потом заново посчитаете crc32 то вы удивитесь.
A>это понятно, удивляться не буду) наверно я не совсем понятно выразился. мне не нужно считать какой-либо хэш по самому файлу, идея была в том чтобы сделать максимально уникальную строку, например из имени файла и его размера (размер + имя уникально в наборе загружаемых файлов) и по этой строке посчитать самый быстрый и маленький (по размеру) хэш (думаю crc32 самый подходящий), а потом использовать полученный хэш как часть уникального идентификатора, а вторая часть была бы просто порядковым номером записи в конкретном файле...

_>>Для 20млрд записай база будет под терабайт.

A>да не просто ТБ, а несколько ТБ — 5-6... это как бы тоже понятно)

A>В принципе вот так вроде работает...

A>
A>unsigned long long int uid = crc32c(0, (const unsigned char*)sStr2Crc32.c_str(), sStr2Crc32.size());
A>BYTE* p = (BYTE*)& uid;
A>p[7] = p[3];
A>p[6] = p[2];
A>p[5] = p[0] * p[1];
A>uid &= 0xFFFFFFFF00000000;
A>uid++;
A>...
A>

A>Теперь 3 старших байта unsigned long long int содержат crc32 (чуть урезанную)), а 5 младших счетчик...

Не понятно какую проблему вы решаете...

Если вам нужен гарантированно уникальный Id который может независимо генериться для любого INSERT`а в базу, то лучше сгенерить какой-нибудь MD5 от уникального набора параметров файла. MD5 алгоритм очень быстрый.

Если вы можете использовать инкремент и назначать файлам порядковый номер 1, 2, 3... , то зачем вам вообще crc32?
Re: Сделать уникальный идентификатор для записи
От: velkin Удмуртия http://blogs.rsdn.org/effective/
Дата: 11.05.19 13:50
Оценка:
Здравствуйте, .alex, Вы писали:

A>Вопрос собственно в том, здраво ли это звучит и как именно установить 3 старший байта и потом инкриминировать 5 нижних отдельно от всех 8 байт...


Звучит как-то не очень.

URI = URL + URN
  Скрытый текст

URI (Uniform Resource Identifier) — единообразный идентификатор ресурса
URL (Uniform Resource Locator) — единообразный указатель ресурса
URN (Uniform Resource Name) — единообразное название ресурса

URL — путь по которому находится ресурс, в нашем случае это файл.
URN — представляет собой пространства имён.

<URN> ::= "urn:" <NID> ":" <NSS>
<NID>
...идентификатор пространства имён (Namespace Identifier)
<NSS>
...строка из определённого пространства имён (Namespace Specific String)


Для опознания файлов логичнее всего использовать хеши:

urn:tree:tiger:7N5OAMRNGMSSEUE3ORHOKWN4WWIQ5X4EBOOTLJY
urn:sha1:XRX2PEFXOOEJFRVUCX6HMZMKS5TWG4K5
urn:btih:QHQXPYWMACKDWKP47RRVIV7VOURXFE5Q
urn:ed2k:354B15E68FB8F36D7CD88FF94116CDC1
urn:md5:834CEF60EF3FD47162420FA25ABF2DFF
urn:md4:bbd810ee7731921c4582daa00bbc531e
urn:tiger:cf13102788e1e6ef6124cb9ca9ef879e4bb04c58fe297dd3
urn:aich:wbtmcm2wrbndylixh3jmwsg4uowzjcqm
urn:whirlpool:dc38ce741d9c8be87a0d715fad951460c5299da2447c3fa8f1057b560f9253c7a017882dcc2390ab602c3b0f5fcf066d6d35f32ffa9b8e5557e1d2f619506873
urn:ripemd160:93f1cb4a43643136d730a3b94b0ebcec66928c02
urn:gost:906fd73511810bafdaa33c05b9957b07edd8dca9b6982c04a86f6c642eb6b062
urn:has160:85c292d359574b89985b2667c9725edb1c7d12fc
urn:snefru128:646b932fee2529db11d05425cff21978
urn:snefru256:35879fc03ca60db551fa26ce8be6a6a04d542cf5a635ab203f95c6f1affb59a6


В этом случае одно из самых худших решений использование crc32. Помимо этого существуют и другие пространства имён.

urn:isbn:5170224575
urn:ietf:rfc:3406
urn:oid:2.16.643
urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66


Разница в том, что они не позволяют взять произвольный файл и однозначно его опознать с помощью хеширования. Надёжность хешей от взлома это отдельный вопрос, но применительно к crc32 здесь даже разговаривать не о чем.

В определённом смысле размеры файлов или других блоков данных это тоже пространства имён.

urn:size:164378
urn:filesize:28244874


Размер файла хорош тем, что для его получения в отличие от того же хеширования не нужно производить никаких вычислений. Но если это база данных, то соединять размер или хеш с другой информацией имеет ряд побочных отрицательных эффектов и ни одного положительного.
1) в базе данных появляются лишние данные занимающие её объём
2) теряется эффект индексации поля "размер файла"

Так же стоит учитывать, что один и тот же файл может лежать в разных местах, то есть в urn он в одном экземпляре, а в url во множестве.

table:urn
..id
..size
..crc32 <= хеш
..md5 <= хеш
..sha1 <= хеш
..и так далее

table:url
..urn <= ссылка на id table:urn
..scheme
..login
..password
..host
..port
..path
..query
..fragment


По поводу хешей ещё скажу, что не важно примитивен ли алгоритм или используется более продвинутый, но лучше всего производить считывание данных лишь один раз. Обычно считывание с диска в оперативную память происходит кусками (chunk), в этот момент текущий кусок можно отправить сразу всем обработчикам вычисляющим различные хеши.
Re[3]: Сделать уникальный идентификатор для записи
От: Kostya.  
Дата: 17.05.19 06:24
Оценка:
Здравствуйте

Ну, можно сделать уникальный ключ из трех (четырех) полей ( имя, дата создания, дата модификации ...)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.