![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Почти уникальный ID
novichek © (2011-03-04 16:22:00)Преследуя репликацию, где данные с клиентов могут передаваться разным способом, необходимо генерировать уникальный ID.
локальное отделение вероятно будет иметь не более 10 ПК.
Как вы думаете, можно ли использовать для генерации уникального ID записи данную функцию?
ID:= genUniID(kodOtdela)
...
function genUniID(id: byte): Int64;
var
x: Int64;
y, m, d, ss: Word;
begin
x:= id;
DecodeDate(date, y, m, d);
y:= y and 15;
x:= x shl 4;
x:= x + y;
x:= x shl 4;
x:= x + m;
x:= x shl 5;
x:= x + d;
DecodeTime(time, y, m, d, ss);
x:= x shl 5;
x:= x + y;
x:= x shl 6;
x:= x + m;
x:= x shl 6;
x:= x + d;
x:= x shl 7;
x:= x + ss;
x:= x shl 7;
result:= x + random(128);
end;
это первое что пришло в голову..
может есть какие красивые варианты?
пока опыта ноль..
Inovet (2011-03-04 18:31:00) [21]> [30] Противный (04.03.11 18:12)
> Поэтому каждому серверу свой уникальный префикс. Без исключений.
Зачем тогда все сложности. Пользуемся генераторами, на каждом отделении выставляем начальное значение на свой диапазон для визуального удобства, например, так:
отд начальное конечное
0 0000000000001 0999999999999
1 1000000000000 1999999999999
2 2000000000000 2999999999999
3 3000000000000 3999999999999
...
Противный (2011-03-04 18:12:00) [22]> novichek (04.03.11 17:55) [29] только проблема тут в том, что на главном сервере так же могут добавлять записи под ID любого отделения.
У главного сервера должен быть свой уникальный префикс. То есть, по сути, ID записи не предназначен для хранения никакой другой инфорамции, кроме как для уникального идентифицирования записи во всей информационной системе. Поэтому каждому серверу свой уникальный префикс. Без исключений.
А если надо хранить информацию о том, от имени какого отделения создана запись - вот тут уже отдельное поле с внешним ключем на справочник отделений.
novichek (2011-03-04 17:55:00) [23]Противный, была такая идея сразу, только проблема тут в том, что на главном сервере так же могут добавлять записи под ID любого отделения.
я вот думаю надо в моей функции убрать последнее добавление случайного числа, подсчитать сколько там остается бит до 64 и генерить в конце какой-то CRC из например мак адреса сетевухи..
а если где и совпадет случайно ид и потеряется при синхронизации одна запись какого-то отделения - ну и хрен с ней (:
спасибо за помощь!
Противный (2011-03-04 17:46:00) [24]Для ускорения процесса генерации можешь инкрементировать NextID в таблице ключиков не на 1 при каждой генерации ключа, а, например, на 10, храня в памяти текущий ID и максимальное выделенное значение. Это даст возможность сгенерировать 10 ключей, обратившись к БД всего один раз. В общем, инкремент NextID может быть переменным, и опередляться в зависимости от ожидаемых операций.
Конецептуально:
TIDGenerator = class
private
FNextID: integer;
FMaxID: integer;
FDepartmentPrexif: integer;
FBlockSize: integer;
protected
procedure AcquireBlock;
public
function NextID: Int64;
property BlockSize: integer read FBlockSize write FBlockSize;
end;
procedure TIDGenerator.AcquireBlock;
begin
BeginTransaction;
try
Query(SELECT NextID AS SelectedNextID FROM IDTable);
Execute(INSERT INTO IDTable(NextID) VALUES (SelectedNextID + FBlockSize));
FMaxID := SelectedNextID + FBlockSize;
CommitTransaction;
except
RollbackTransaction;
raise;
end;
end;
function TIDGenerator.NextID: Int64;
begin
if FNextID = FMaxID then
AcquireBlock;
Result := FDepartmentPrexif shl 32 + FNextID;
FNextID := FNextID + 1;
end;
Противный (2011-03-04 17:32:00) [25]> Jeer © (04.03.11 17:13) [18] Глупости, именно это и есть панацея в таких случаях
Доступ к 2 полям типа Int64 медленнее, чем к одному полю типа GUID. Что-то мне подсказывает, что медленнее более, чем в 2 раза. Соответственно, все операции по индексированию и поиску...
2 novichek
Сделай в БД табличку с двумя полями:
DepartmentUniquePrefix integer
NextID integer
Там храни префикс отделения и следующий идентификатор.
А первичные ключи в таблицах сделай Int64, первые 32 бита - DepartmentUniquePrefix, вторые 32 бита - ID.
Напиши функцию по типу CreateNextID: Int64, в которой и реализуй логику генерации ключей.
clickmaker (2011-03-04 17:27:00) [26]> Здесь нет проблем
при репликации есть. Собственно, об ней и ветка
Jeer (2011-03-04 17:21:00) [27]
> А вот их и надо генерить
Задача генерации составляющих PK решается административно-техническими методами. Здесь нет проблем.
Sergey13 (2011-03-04 17:21:00) [28]> [19] novichek (04.03.11 17:15)
> а так я написал, отдал софт они сами ставить будут где хотят..
Не взлетит.
> потом с этих серверов будут передавать данные на главный где будут собираться до кучи.
Пришли адресок, может и мы чего пульнем ради женского праздника. 8-)
Jeer (2011-03-04 17:20:00) [29]
> предложили уже
Предложен был составной PK, как наиболее правильное решение в таких случаях.
Что в основе составного PK должно лежать - решать автору проекта.
Может у них по несколько серверов на пользователя раздают :)
clickmaker (2011-03-04 17:18:00) [30]> Как Вас понимать, Саид ?
составной ID - это обычно ID, образованный отношениями между сущностями. UserID - ObjectID, к примеру. Он не уникален сам по себе. Его делают уникальным состовляющие.
А вот их и надо генерить
clickmaker (2011-03-04 17:16:00) [31]я бы остановился на дате/времени + некая локальноуникальная хрень типа IP сервера. Ну, собственно в [14] предложили уже
Jeer (2011-03-04 17:16:00) [32]
> clickmaker © (04.03.11 17:12) [16]
>
> а нафига составному быть уникальным? Уникальными должны
> быть составляющие
>
Как Вас понимать, Саид ?
Именно составной, в рамках организации, и должен быть уникальным.
И не фик вытворять чудеса с обрезанием :)
novichek (2011-03-04 17:15:00) [33]Inovet ©, если бы я ставил может номер сервера и нормально было бы..
а так я написал, отдал софт они сами ставить будут где хотят..
развернули в локальной сетке сервер, прописали в клиентах данные соединения и вперед.
потом с этих серверов будут передавать данные на главный где будут собираться до кучи.
Jeer (2011-03-04 17:13:00) [34]
> не хотелось бы конечно держать составной первичный индекс.
Глупости, именно это и есть панацея в таких случаях.
novichek (2011-03-04 17:12:00) [35]мда..
Jeer ©
я пока перемалываю в голове.. не хотелось бы конечно держать составной первичный индекс.
Противный, а вы не помните где резать?
clickmaker (2011-03-04 17:12:00) [36]а нафига составному быть уникальным? Уникальными должны быть составляющие
Сергей М. (2011-03-04 17:08:00) [37]
> если отрезать половину
Нафига резать ?
Два Int64-поля в составной ключ - и всех делов.
Можно и одно char(16)-поле, указав чарсет OCTETS
Inovet (2011-03-04 17:06:00) [38]> [9] novichek (04.03.11 16:56)
> прийдется что то мудрить своё..
Номер сервера в дополнение.
Sergey13 (2011-03-04 17:05:00) [39]> [7] Jeer © (04.03.11 16:34)
> Составной PK
+100500. Чего мудрить то?
clickmaker (2011-03-04 17:01:00) [40]главное, чтобы время было одинаковое