2009-08-23 10 views
1

Из моего опыта я узнал, что с использованием столбца типа данных суррогата INT в качестве первичного ключа esp. ключевой столбец IDENTITY обеспечивает лучшую производительность, чем использование столбца данных GUID или char/varchar в качестве первичного ключа. Я пытаюсь использовать ключ IDENTITY как первичный ключ, где это возможно. Но недавно я столкнулся с схемой, в которой таблицы были разделены по горизонтали и управлялись через представление с разделением. Таким образом, таблицы не могли иметь столбец IDENTITY, поскольку это сделало бы Partitioned View не обновляемым. Одна из них заключалась в создании таблицы манекенов «keygenerator» с столбцом идентификатора для генерации идентификаторов для первичного ключа. Но это означало бы наличие таблицы «keygenerator» для каждого из Partitioned View. Моя следующая мысль заключалась в том, чтобы использовать float в качестве первичного ключа. Причина заключается в следующем ключе алгоритм, который я разработалИспользование представления 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 или обугленного/VARCHAR в качестве первичных ключей. Также важно то, что разбиение столбца float будет частью составного ключа.

ответ

1

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

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

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

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

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

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

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

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

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

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

НТН

+0

Я, наконец, решил использовать составной первичный ключ, как это предложил PDaddy. Первоначально я думал, что использование составных клавиш может ухудшить производительность, но в моем случае использование комбинации полей Int и datetime не имеет большого значения. Совокупный ключ не кластеризуется, и я создал кластерный индекс в поле Int – devanalyst

+0

Забыл упомянуть, что кластерный индекс создается в поле Int, потому что он будет использоваться в объединениях – devanalyst

1

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

+0

Блокировка всей таблицы и поиска в следующий свободный идентификатор - этот метод я стараюсь избегать, так как блокировка таблицы с миллионами строк и сканирования для следующего доступного идентификатора может стать бутылка производительность шея Предварительное выделение диапазонов идентификаторов - я пытаюсь выяснить, может ли быть выведен метод, который позволяет избежать сканирования таблиц таким образом. – devanalyst

+0

На самом деле было бы только заблокировать индекс. И поиск миллиона + индекс не так уж плох. То есть, в конце концов, для чего они нужны. –

+0

Я только что упомянул о блокировке стола для полноты, но на самом деле не рекомендую его (в сильно параллельных средах). –

0

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

Смежные вопросы