Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2011.06.12;
Скачать: [xml.tar.bz2];

Вниз

Почти уникальный ID   Найти похожие ветки 

 
novichek   (2011-03-04 16:22) [0]

Преследуя репликацию, где данные с клиентов могут передаваться разным способом, необходимо генерировать уникальный 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;


это первое что пришло в голову..

может есть какие красивые варианты?
пока опыта ноль..


 
clickmaker ©   (2011-03-04 16:26) [1]

СУБД какая?


 
RWolf ©   (2011-03-04 16:27) [2]

сгенерировать GUID, конечно.


 
Медвежонок Пятачок ©   (2011-03-04 16:27) [3]

а может просто CoCreateGuid?


 
novichek   (2011-03-04 16:31) [4]

FireBird как и посоветовали.

ну как понимаю GUID будет храниться в строке..

как то ключеврой индекс не хочется иметь строку..


 
Сергей М. ©   (2011-03-04 16:33) [5]


> GUID будет храниться в строке


Как будешь хранить - так и будет храниться.
Не хочешь в строке - храни в Int64


 
RWolf ©   (2011-03-04 16:34) [6]

typedef struct _GUID {
   unsigned long Data1;
   unsigned short Data2;
   unsigned short Data3;
   unsigned char Data4[8];
} GUID;


и где тут строка?


 
Jeer ©   (2011-03-04 16:34) [7]

Составной PK


 
Inovet ©   (2011-03-04 16:39) [8]

> [4] novichek   (04.03.11 16:31)
> FireBird как и посоветовали.

Генераторы в нём для этого предназначены.


 
novichek   (2011-03-04 16:56) [9]

Inovet ©, так а что генераторы? в каждом отделе свой сервер. потом общие данные будут стекаться на главный. ещё правда не знаю как, репликации в FireBird нету, прийдется что то мудрить своё..

RWolf © , я х.з., читал умные статьи:
http://www.ibase.ru/devinfo/test2.htm
"Некоторые сервера позволяют хранить GUID в его двоичном представлении, размером 16 байт. В IB нет возможности сохранить двоичное значение в строке, а blob для таких целей использовать будет неэффективно. Поэтому выход остается один - хранить GUID как строку."


 
Jeer ©   (2011-03-04 16:58) [10]


> Поэтому выход остается


Составной PK - еще раз.


 
Противный   (2011-03-04 16:58) [11]

> Сергей М. ©   (04.03.11 16:33) [5]
> > GUID будет храниться в строке
> Как будешь хранить - так и будет храниться.
> Не хочешь в строке - храни в Int64


GUID 128-битный. Хотя, если отрезать половину, то влезет. Но надо знать откуда резать, а то уникальности не получится. То есть, есть ньюансы...

> novichek   (04.03.11 16:22)  Как вы думаете, можно ли использовать для генерации уникального ID записи данную функцию?

Использовать время для генерации первичного ключа - не лучшее решение. Точнее, плохое решение. Или ты готов гарантировать точное время на всех компьютерах?


 
clickmaker ©   (2011-03-04 17:01) [12]

главное, чтобы время было одинаковое


 
Sergey13 ©   (2011-03-04 17:05) [13]

> [7] Jeer ©   (04.03.11 16:34)
> Составной PK
+100500. Чего мудрить то?


 
Inovet ©   (2011-03-04 17:06) [14]

> [9] novichek   (04.03.11 16:56)
> прийдется что то мудрить своё..

Номер сервера в дополнение.


 
Сергей М. ©   (2011-03-04 17:08) [15]


> если отрезать половину


Нафига резать ?
Два Int64-поля в составной ключ - и всех делов.
Можно и одно char(16)-поле, указав чарсет OCTETS


 
clickmaker ©   (2011-03-04 17:12) [16]

а нафига составному быть уникальным? Уникальными должны быть составляющие


 
novichek   (2011-03-04 17:12) [17]

мда..  

Jeer ©

я пока перемалываю в голове.. не хотелось бы конечно держать составной первичный индекс.

Противный,  а вы не помните где резать?


 
Jeer ©   (2011-03-04 17:13) [18]


> не хотелось бы конечно держать составной первичный индекс.


Глупости, именно это и есть панацея в таких случаях.


 
novichek   (2011-03-04 17:15) [19]

Inovet ©, если бы я ставил может номер сервера и нормально было бы..

а так я написал, отдал софт они сами ставить будут где хотят..
развернули в локальной сетке сервер, прописали в клиентах данные соединения и вперед.

потом с этих серверов будут передавать данные на главный где будут собираться до кучи.


 
Jeer ©   (2011-03-04 17:16) [20]


> clickmaker ©   (04.03.11 17:12) [16]
>
> а нафига составному быть уникальным? Уникальными должны
> быть составляющие
>


Как Вас понимать, Саид ?

Именно составной, в рамках организации, и должен быть уникальным.
И не фик вытворять чудеса с обрезанием :)


 
clickmaker ©   (2011-03-04 17:16) [21]

я бы остановился на дате/времени + некая локальноуникальная хрень типа IP сервера. Ну, собственно в [14] предложили уже


 
clickmaker ©   (2011-03-04 17:18) [22]

> Как Вас понимать, Саид ?

составной ID - это обычно ID, образованный отношениями между сущностями. UserID - ObjectID, к примеру. Он не уникален сам по себе. Его делают уникальным состовляющие.
А вот их и надо генерить


 
Jeer ©   (2011-03-04 17:20) [23]


> предложили уже


Предложен был составной PK, как наиболее правильное решение в таких случаях.
Что в основе составного PK должно лежать - решать автору проекта.
Может у них по несколько серверов на пользователя раздают :)


 
Sergey13 ©   (2011-03-04 17:21) [24]

> [19] novichek   (04.03.11 17:15)
> а так я написал, отдал софт они сами ставить будут где хотят..

Не взлетит.

> потом с этих серверов будут передавать данные на главный где будут собираться до кучи.
Пришли адресок, может и мы чего пульнем ради женского праздника. 8-)


 
Jeer ©   (2011-03-04 17:21) [25]


> А вот их и надо генерить


Задача генерации составляющих PK решается административно-техническими методами. Здесь нет проблем.


 
clickmaker ©   (2011-03-04 17:27) [26]

> Здесь нет проблем

при репликации есть. Собственно, об ней и ветка


 
Противный   (2011-03-04 17:32) [27]

> Jeer ©   (04.03.11 17:13) [18] Глупости, именно это и есть панацея в таких случаях

Доступ к 2 полям типа Int64 медленнее, чем к одному полю типа GUID. Что-то мне подсказывает, что медленнее более, чем в 2 раза. Соответственно, все операции по индексированию и поиску...

2 novichek

Сделай в БД табличку с двумя полями:

DepartmentUniquePrefix integer
NextID integer

Там храни префикс отделения и следующий идентификатор.

А первичные ключи в таблицах сделай Int64, первые 32 бита - DepartmentUniquePrefix, вторые 32 бита - ID.

Напиши функцию по типу CreateNextID: Int64, в которой и реализуй логику генерации ключей.


 
Противный   (2011-03-04 17:46) [28]

Для ускорения процесса генерации можешь инкрементировать 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;


 
novichek   (2011-03-04 17:55) [29]

Противный, была такая идея сразу, только проблема тут в том, что на главном сервере так же могут добавлять записи под ID любого отделения.

я вот думаю надо в моей функции убрать последнее добавление случайного числа, подсчитать сколько там остается бит до 64 и генерить в конце какой-то CRC из например мак адреса сетевухи..

а если где и совпадет случайно ид и потеряется при синхронизации одна запись какого-то отделения - ну и хрен с ней (:

спасибо за помощь!


 
Противный   (2011-03-04 18:12) [30]

> novichek   (04.03.11 17:55) [29] только проблема тут в том, что на главном сервере так же могут добавлять записи под ID любого отделения.

У главного сервера должен быть свой уникальный префикс. То есть, по сути, ID записи не предназначен для хранения никакой другой инфорамции, кроме как для уникального идентифицирования записи во всей информационной системе. Поэтому каждому серверу свой уникальный префикс. Без исключений.

А если надо хранить информацию о том, от имени какого отделения создана запись - вот тут уже отдельное поле с внешним ключем на справочник отделений.


 
Inovet ©   (2011-03-04 18:31) [31]

> [30] Противный   (04.03.11 18:12)
> Поэтому каждому серверу свой уникальный префикс. Без исключений.

Зачем тогда все сложности. Пользуемся генераторами, на каждом отделении выставляем начальное значение на свой диапазон для визуального удобства, например, так:

отд  начальное     конечное
0    0000000000001 0999999999999
1    1000000000000 1999999999999
2    2000000000000 2999999999999
3    3000000000000 3999999999999
...


 
_Юрий   (2011-03-04 20:30) [32]

Guid + индекс. Первичным ключом не делать, там обычный автоникремент.
3 года работы полет нормальный.


 
Противный   (2011-03-04 20:50) [33]

> _Юрий   (04.03.11 20:30) [32] Первичным ключом не делать, там обычный автоникремент.

Как тебя понимать?

> _Юрий   (04.03.11 20:30) [32] 3 года работы полет нормальный.

Ну и? Предлагаешь везде в качестве ключей использовать GUID?


 
KilkennyCat ©   (2011-03-04 21:19) [34]


> Inovet ©   (04.03.11 18:31) [31]

дык генератор-то тогда зачем? выделить всем свой диапазон и все.


 
Inovet ©   (2011-03-04 21:26) [35]

> [34] KilkennyCat ©   (04.03.11 21:19)
> дык генератор-то тогда зачем?

Так это в ИБ ФБ терминологии генератор. Для отделения № 2 выставить начальное значение 2000000000000 и пусть растёт, предполагаем, что в таблице не будет более 1000000000000 записей. И так для каждой таблицы. Это если ИД отделения в отдельном поле не надо.


 
novichek   (2011-03-04 22:31) [36]

да тут проблема в том, что неизвестно сколько будет отделений..
отсюда непонятно как и генерить префикс сервера.
и могут в одном отделении развернуть два сервера.

все-таки думаю временной штамп + CRC мак сетевухи вполне пойдет..


 
KilkennyCat ©   (2011-03-04 22:38) [37]


> все-таки думаю временной штамп + CRC мак сетевухи вполне
> пойдет

велосипед.
я тоже недавно изобретал такой велосипед.
Спасибо, Юрий Федоров избавил от сего извращения: GUID и на этом все.


 
novichek   (2011-03-04 22:51) [38]

ну так куда 128 бит? два поля делать?

ид уникальный должен быть в нескольких таблицах.
где потом и будут например связи один ко многим..

желательно под ид иметь одно поле.. и не строку..


 
Юрий Зотов ©   (2011-03-05 00:18) [39]

Пожиратели GUID"ов, не приближайте день X.


 
KilkennyCat ©   (2011-03-05 00:44) [40]


> novichek   (04.03.11 22:51) [38]
и не строку..

а какая разница, строка или нет?



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2011.06.12;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.005 c
2-1295769353
Holod
2011-01-23 10:55
2011.06.12
DBLookupComboBox и фильтрация


2-1299244957
novichek
2011-03-04 16:22
2011.06.12
Почти уникальный ID


2-1299150042
fantoma
2011-03-03 14:00
2011.06.12
Печать в fastreport


15-1298033535
oxffff
2011-02-18 15:52
2011.06.12
Языки и циклические зависимости между блоками компиляции(units)


2-1299086314
fynjy93
2011-03-02 20:18
2011.06.12
dbnavigator





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский