SQL Server BIGINT или DECIMAL (18,0) для первичного ключа

у нас есть база данных SQL Server 2005, для которой мы хотим улучшить производительность массового удаления / вставки / выбора, и я замечаю, что она использует decimal(18,0) для первичных ключей. Я понимаю, что это даст нам гораздо больше значений, чем bigint но надеялся, что это может быть быстрая победа и должна длиться много миллионов лет роста по моим расчетам.

Я вижу в .net docs десятичные числа занимают 16 байт вместо 8, требуемых longs, но в SQL Server это выглядит так bigint занимают 8 байт но decimal(18,0) принимает только 5 байт - как Также видно select DATALENGTH(max(id)) from table. Правильно ли это?

есть ли другая причина bigint может быть медленнее, или я должен придерживаться decimal(18,0)?

2 ответов


DATALENGTH бросает в varchar перед подсчетом байтов. Так что ваш Макс значение

9 байтов можно доказать с этим. sys.колонки имеет столбец max_length (decimal-фиксированная длина, поэтому всегда 9 байт, прежде чем вы спросите иначе)

CREATE TABLE dbo.foo (bar decimal(18,0))
GO
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('foo') 
GO
DROP TABLE dbo.foo
GO

по причинам наследия,decimal(18, 0) часто использовался в качестве суррогата для "64-битного целого числа" до добавления bigint с SQL Server 2000.

decimal(18, 0) и bigint примерно одинаковые диапазон: decimal - это еще один байт при 9 байтах согласно документации

кроме того, простое целое число будет дробно (возможно, не измеримо) быстрее, чем десятичное. Говоря, что если в следующем году ожидается более 4 миллиардов строк или 5, то производительность должна иметь значение. Если это не так, то просто используйте int


вы получаете этот диапазон с bigint:

-2^63 to 2^63-1 

also known as roughly:

-9.2 x 10^18 to 9.2 x 10^18

вы получаете этот диапазон с decimal (18,0):

-10^18 to 10^18

Decimal: байты хранения на точность

Precision    Storage Bytes
1-9:         5
10-19:       9
20-28:       13
29-38:       17

целочисленные типы и байты хранения

integer type    Storage Bytes
bigint          8
int             4
smallint        2
tinyint         1

мысли

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

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

чтобы решить вашу конкретную проблему, если вы хотите больший диапазон, используйте Decimal (38,0). Это дает вам:

-10^38 to 10^38

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

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

ссылки