Подскажите какие есть практики для формирования УИД при добавлении записей в БД одновременно из нескольких независимых потоков ну и в несколько сессий «заливки».
Постараюсь объяснить подробнее.
Есть, например, 100 xml файлов, моя программа читает их, например, одновременно в 10 потоков (1 поток – 1 файл) и соответственно каждый поток делает bulkinsert в общую таблицу в БД.
И нужно сделать УИД для каждой записи в формате bigint (составной УИД не подходит, т.к. в последствии этот УИД будет использоваться для построения полнотекстового индекса по данной таблице).
Я делал так: из 8 байт bigint я использовал 5 младших байт, как счетчик текущей записи в текущем файле (в одном файле записей может быть больше 2^32 но меньше 2^40),
а в 3 старших засовывал crc32, посчитанную по строке, которая состоит из имени файла + переведенный в строку размер фала (это на случай не уникальности имен файлов, комбинация имя + размер – уникально),
ну и из-за того, что у меня всего 3 байта для crc32 я два оставлял как есть а для 3 и 4 делал xor и добавлял в оставшийся байт bigint.
В принципе все работало, но если в загрузке участвует несколько тысяч файлов, то моей доморощенной crc32 стало не хватать, появились коллизии…
Так вот собственно вопрос, что можно придумать, притом без хранения информации о предыдущей сессии?
Если бы не было несколько сессий «заливки», то понятно перед заливкой каждому потоку даем свой ИД и льем, но как быть в второй и последующих сессиях заливки, от чего отталкиваться, время я тоже не придумал, как засунуть в 3 байта…
Re: Как сформировать уникальный идентификатор для нескольких потоков и сессий
Здравствуйте, .alex, Вы писали:
A>Есть, например, 100 xml файлов, моя программа читает их, например, одновременно в 10 потоков (1 поток – 1 файл) и соответственно каждый поток делает bulkinsert в общую таблицу в БД. A>И нужно сделать УИД для каждой записи в формате bigint (составной УИД не подходит, т.к. в последствии этот УИД будет использоваться для построения полнотекстового индекса по данной таблице).
Автоинкремент? Или вы забыли упомянуть, что по этому ключу нужно найти нужный элемент в файле?
Делайте составной, потом добавляйте stored вычисляемую колонку и делайте по ней индекс.
Re: Как сформировать уникальный идентификатор для нескольких потоков и сессий
Здравствуйте, .alex, Вы писали:
A>Подскажите какие есть практики для формирования УИД при добавлении записей в БД одновременно из нескольких независимых потоков ну и в несколько сессий «заливки».
Использовать sequence предоставляемый базой?
При отсутствии можно эмулировать через автоинкремент.
Re: Как сформировать уникальный идентификатор для нескольких потоков и сессий
Здравствуйте, .alex, Вы писали:
A>В принципе все работало, но если в загрузке участвует несколько тысяч файлов, то моей доморощенной crc32 стало не хватать, появились коллизии… A>Так вот собственно вопрос, что можно придумать, притом без хранения информации о предыдущей сессии?
Guid какой-нибудь последней версии, v4, он статистически исключает коллизии и не зависит от сессии или состояния. Поэтому его используют в распределенных системах для генерации ID сущностей.
Re: Как сформировать уникальный идентификатор для нескольких потоков и сессий
Здравствуйте, gandjustas, Вы писали: G>Автоинкремент? Или вы забыли упомянуть, что по этому ключу нужно найти нужный элемент в файле?
Автоинкремент имеете ввиду IDENTITY? Если да, то пробовал, не подходит — скорость загрузки падает на порядки (даже не в разы)... G>Делайте составной, потом добавляйте stored вычисляемую колонку и делайте по ней индекс.
А можете пример для MSSQL привести, что-то не понял как это...
Здравствуйте, vmpire, Вы писали: V>Использовать sequence предоставляемый базой?
Попробую, а пример небольшой можно? V>При отсутствии можно эмулировать через автоинкремент.
Уже писал — не подходит из-за снижения скорости...
Здравствуйте, gyraboo, Вы писали: G>Guid какой-нибудь последней версии, v4, он статистически исключает коллизии и не зависит от сессии или состояния. Поэтому его используют в распределенных системах для генерации ID сущностей.
Получается его нужно будет для каждой записи генерировать? Думаю будет значительная просадка в скорости импорта... А если один раз для потока, то не понятно как его в 3 байта засунуть...
Re: Как сформировать уникальный идентификатор для нескольких потоков и сессий
Здравствуйте, .alex, Вы писали:
V>>Использовать sequence предоставляемый базой? A>Попробую, а пример небольшой можно? https://learn.microsoft.com/en-us/previous-versions/sql/sql-server-2012/ff878058(v=sql.110)
Для Вашего случая имеет смысл получать номера пачками, например, с помощью sp_sequence_get_range
V>>При отсутствии можно эмулировать через автоинкремент. A>Уже писал — не подходит из-за снижения скорости...
Если в лоб, то да. Но можно попробовать делать вставку для получения ID сразу пакетами.
Или получать ID сразу для пакета значений, например из 100 штук, а внутри неё уже нумеровать самостоятельно.
Re[2]: Как сформировать уникальный идентификатор для нескольких потоков и сессий