Десятичный SQL Server (9, 0) против INT

15

Один из наших клиентов использует для некоторых столбцов тип данных DECIMAL(18,0)в своей базе данных SQL Server 2008R2. Поскольку столбцы растут довольно медленно, он недавно предложил изменить тип данных, DECIMAL(5,0)чтобы восстановить некоторое хранилище.

Согласно библиотеке MSDN , объем памяти типа DECIMAL(5,0)данных, как и DECIMAL(9,0)тип данных, составляет 5 байтов. INTна 1 байт меньше, но может хранить все в диапазоне от -2 ^ 31 до 2 ^ 31 вместо от -99 999 до 99 999, которые DECIMAL(5,0)можно хранить. Даже самый большой, DECIMALкоторый умещается в 5 байтов ( DECIMAL(9,0)), может хранить только целые числа в диапазоне от -999,999,999 до 999,999,999 (что составляет менее половины INTпредложения диапазона в 4 байта).

Я могу думать о двух «преимуществах» использования DECIMALнад INT:

  • Возможность добавить масштаб после, не используя больше места для хранения
  • Возможность масштабирования до 38 цифр без изменения типа данных

но это не настоящие преимущества на мой взгляд:

  • Добавление масштаба к целым числам имеет смысл только в очень немногих случаях (в большинстве случаев, когда масштаб действительно имеет значение, его также можно добавить заранее)
  • SQL Server рассматривает каждую комбинацию точности / масштаба как отдельный тип данных, поэтому при увеличении точности или масштаба тип данных не остается один.

Это заставляет меня задуматься: каково дополнительное преимущество типа DECIMAL(5,0)данных для целых чисел?

vstrien
источник
1
Одно преимущество может быть пятизначным пределом. Но мне интересно, сколько места для хранения вы можете сэкономить с таким изменением.
Дезсо
3
IMO, если вам просто нужно убедиться, что значения столбцов попадают в диапазон, используйте проверочное ограничение. Я думаю, что единственное соображение здесь будет, если есть вероятность того, что этот столбец требует дробных значений в будущем.
Джон Зигель
3
Если они беспокоятся о месте хранения, они лучше подходят для сжатия, чем это. Нет ощутимого преимущества использования десятичного числа (x, 0) вместо int / bigint.
Роберт Л Дэвис
7
Другое различие между decimal(x,0)и целочисленным типом проявляется в арифметическом делении. Если вы делите int на int, вы получаете int. Если вы разделите десятичное число (x, 0) на int, вы получите десятичное число (x + 6,6).
Андрей М
@AndriyM, я думаю, что это самая большая выгода. Перефразируйте это в ответ вместо комментария, и я отмечу это как ответ.
Встриен

Ответы:

8

Я согласен с тем, что нет никаких реальных преимуществ с точки зрения пространства хранения, если вы сравниваете DECIMAL (9, 0) с INT или DECIMAL (18, 0) с BIGINT. (В пределах одного байта.)

С точки зрения обработки, как @Andriy говорит, что DECIMAL естественно разделится на тип, который не теряет дробную часть, если это важно для вас.

С другой стороны, работа с нативными типами INT намного быстрее с числовой точки зрения, если вы выполняете много операций SUM () или сравнений (таких как поиск по значениям), поскольку они более эффективно передаются ЦП по конвейеру. Сравнение int - это два кода операции сборки (MOV, CMP), но любое десятичное сравнение будет много, намного больше.

Крис Чубб
источник
Ваш ответ имеет смысл, но процессор не знает типов данных. Таким образом, один тип данных из 4 байтов сравнивается так же быстро, как другой тип данных из 4 байтов. Можете ли вы показать (например, с помощью повторяемого теста производительности), что при использовании DECIMAL(9, 0)вместо « INT?» Наблюдается снижение производительности ?
Встриен
2
Я думал, что смогу, но я признаю, что мои тесты неубедительны. Возможно, SQL проводит оптимизацию, чтобы свести задачу к целочисленной математике. Мой тестовый стенд: `--Выбор сравнения SET @StartTime = SYSDATETIME () WHILE (@CounterINT <@SizeINT) SET @CounterINT = @CounterINT + 1 ПЕЧАТЬ 'INT взял' + CONVERT (VARCHAR (20), DATEDIFF (миллисекунда, @StartTime) , SYSDATETIME ())) + «миллисекунды» --Decimal SET @StartTime = SYSDATETIME () WHILE (@CounterDEC <@SizeDEC) SET @CounterDEC = @CounterDEC + 1 ПЕЧАТЬ 'DEC взял' + CONVERT (VARCHAR (20), DATIFF (миллисекунда, @StartTime, SYSDATETIME ())) + «миллисекунды» `
Крис Чубб
Я думаю, что SQL Server действительно что-то там оптимизирует. Несмотря на то, что оптимизация DECIMALвсе же занимает обычно немного больше времени (по крайней мере, на моей системе разработки). В ходе 10 тестов около 51 мс DEC против 46 мс INT.
Встриен
2

Похоже, не будет никаких преимуществ с точки зрения места для хранения.

Если ваш клиент обеспокоен тем, что ваши значения будут больше, чем 2 ^ 32-1 (максимальное положительное значение, которое может хранить целое число), вам следует рассмотреть возможность перехода к BigInt - с 64 битами ( 8 байтов) .

AlexTheDeveloper
источник