Использование представления даты и времени в качестве первичного ключа - PullRequest
1 голос
/ 23 августа 2009

Из моего опыта я узнал, что использование суррогатного столбца типа INT в качестве первичного ключа esp. ключевой столбец IDENTITY предлагает лучшую производительность, чем использование GUID или столбца типа данных char / varchar в качестве первичного ключа. Я пытаюсь использовать ключ IDENTITY в качестве первичного ключа, где это возможно. Но недавно я наткнулся на схему, в которой таблицы были разделены по горизонтали и управлялись через разделенное представление. Поэтому в таблицах не может быть столбца IDENTITY, поскольку это сделает секционированное представление не подлежащим обновлению. Одним из способов решения этой проблемы было создание фиктивной таблицы 'keygenerator' с столбцом идентификаторов для генерации идентификаторов для первичного ключа. Но это будет означать наличие таблицы «keygenerator» для каждого секционированного представления. Моей следующей мыслью было использовать float в качестве первичного ключа. Причина в следующем ключевом алгоритме, который я разработал

DECLARE @KEY FLOAT

SET @KEY = CONVERT(FLOAT,GETDATE())/100000.0 

SET @KEY = @EMP_ID + @KEY

Heres how it works.

CONVERT(FLOAT,GETDATE()) 

дает представление с плавающей точкой текущей даты и времени, поскольку внутренне все даты и времени представлены SQL в виде значения с плавающей точкой.

CONVERT(FLOAT,GETDATE())/100000.0 

преобразует представление с плавающей точкой в ​​полное десятичное значение, т. Е. Все цифры ставятся справа от ".".

@KEY = @EMP_ID + @KEY

добавляет идентификатор сотрудника, который является целым числом к ​​этому десятичному значению.

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

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

Так что для Emp Ids 11 и 12 у меня есть ключевые значения, такие как 12.40046693321566357, 11.40046693542361111

Но меня беспокоит вопрос о том, предлагают ли типы данных с плавающей точкой в ​​качестве первичного ключа преимущества по сравнению с выбором GUID или char / varchar в качестве первичных ключей. Также важно то, что разбиение столбца с плавающей точкой будет частью составного ключа.

Ответы [ 3 ]

1 голос
/ 23 августа 2009

Также важно то, что разбиение столбца с плавающей точкой будет частью составного ключа.

Что? Зачем? Вы прошли через большие усилия, пытаясь сделать эту ценность для сотрудника / времени уникальной, что еще вам понадобится в первичном ключе? И с другой стороны этого вопроса, другие компоненты вашего ключа уже уникальны? Если так, то почему бы просто не использовать их?

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

  • Сначала я беспокоился о производительности. Но число с плавающей запятой всего 8 байтов (при условии, что ваша СУБД использует IEEE 754 double), что не так уж и много. Это не хуже, чем наличие 64-битного целого числа в качестве ключа или двух 32-битных целых. Ваш процесс генерации ключей - единственное, что может замедлиться, но даже не намного.
  • Я тогда беспокоился об уникальности. Эта схема не гарантирует , что вы не сгенерируете один и тот же ключ дважды. Но, учитывая ваше утверждение, что комбинация user и datetime будет уникальной, тогда это может сработать:
    • Двойной IEEE 754 имеет точность 53 бита.
    • Дата и время будут использовать 42 бита. Предположения:
      • Разрешение даты и времени составляет 1/300 секунды (3,33 ... мс). Это верно для MS SQL Server, по крайней мере.
      • потолок (бревно 2 (86400 * 300 * 100000)) = 42
    • Это оставляет 9 бит для вашего сотрудника ID. Если идентификатор сотрудника больше 511, вы потеряете часть даты и времени, но это будет порядка миллисекунд. Ваш идентификатор сотрудника может достичь 131071, прежде чем вы потеряете точность более чем на секунду.
  • Затем я беспокоился о сложности поиска значения ключа позже. Учитывая проблему 0,2! = 0,1 + 0,1, всегда возникает вопрос о равенстве с плавающей точкой. Но нет никакой причины, по которой вы будете выполнять какие-либо вычисления для этого значения ключа, и, вероятно, оно будет в двойном формате IEEE 754 в любой момент времени (будь то в таблице, в хранимых переменных процесса или в переменных вашего исполняемого файла), затем оно никогда не должно меняться и может рассматриваться как уникальное 64-битное значение.

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

Я все еще задаюсь вопросом, является ли это лучший метод, хотя, или если это даже необходимо.

  • Разве другие компоненты составного ключа не могут использоваться самостоятельно (т. Е. Как натуральный ключ)?

  • Вы могли бы , как вы предлагаете, хранить последовательный начальный ключ в другой таблице. И вам потребуется только одна таблица, а не одна таблица на раздел, как вы предполагаете. Вам просто понадобятся два столбца в этой таблице: один для номера раздела и один для текущего значения идентификатора этого раздела.

  • Использование GUID или первичного ключа varchar не исключено. Многие люди делают это на разных столах. Это не убьет вашу производительность. И это может быть более простым или, по крайней мере, более понятным, чем эта схема.

  • Если ваш составной ключ уже содержит идентификатор сотрудника, вы можете просто добавить в ключ столбец даты и времени и назвать его днем. Или, если нет, вы можете добавить оба столбца. Нет причин для того, чтобы смешивать их вместе.

НТН

1 голос
/ 23 августа 2009

Я бы не стал рассматривать такую ​​неортодоксальную схему генерации ключей - это похоже на неудачный взлом. Почему бы вам просто не использовать целые числа? Существует много способов и алгоритмов для координации генерации распределенных ключей. От блокировки всей таблицы (таблиц) и поиска следующего свободного идентификатора по предварительно распределенным диапазонам идентификаторов для каждого клиента до получения его из конкретной информации клиента (аналогично вашему сотруднику + предложение времени).

0 голосов
/ 23 августа 2009

Поскольку вы не упомянули rdbms, я предположу SQL-сервер. При создании первичного ключа также создается кластерный индекс для этого ключа. Таблица отсортирована в порядке этого ключа. При использовании Guids в качестве первичного ключа (с кластеризованным индексом) каждая вставка означает переупорядочение таблицы. Это также относится к вашему представлению с плавающей точкой. Помимо других проблем, если вы хотите использовать эту схему, не создавайте кластерный индекс для этого первичного ключа.

...