Dziesiętny SQL Server (9, 0) vs INT

15

Jeden z naszych klientów używa w niektórych kolumnach typu danych DECIMAL(18,0)w swojej bazie danych SQL Server 2008R2. Ponieważ kolumny rosną dość wolno, ostatnio zaproponował zmianę typu danych, DECIMAL(5,0)aby odzyskać trochę pamięci.

Według biblioteki MSDN miejsce do przechowywania DECIMAL(5,0)typu danych wynosi, podobnie jak DECIMAL(9,0)typ danych, 5 bajtów. INTjest o 1 bajt mniejszy, ale może przechowywać wszystko w zakresie od -2 ^ 31 do 2 ^ 31 zamiast -99 999 do 99 999, które DECIMAL(5,0)mogą przechowywać. Nawet największa, DECIMALktóra mieści się w 5 bajtach ( DECIMAL(9,0)), może przechowywać tylko liczby całkowite z zakresu od -999,999,999 do 999,999,999 (co stanowi mniej niż połowę INToferty zakresu w 4 bajtach).

Mogę wymyślić dwie „zalety” korzystania DECIMALz INT:

  • Możliwość późniejszego dodania skali bez zajmowania większej przestrzeni dyskowej
  • Możliwość skalowania dokładności do 38 cyfr, bez zmiany typu danych

ale moim zdaniem nie są to realne korzyści:

  • Dodanie skali do liczb całkowitych ma sens tylko w nielicznych przypadkach (w większości przypadków, w których skala robi różnicę, można ją również dodać wcześniej)
  • SQL Server widzi każdą kombinację precyzji / skali jako inny typ danych, więc typ danych nie jest pozostawiony samemu sobie podczas zwiększania precyzji lub skali.

Zastanawiam się: jaka jest dodatkowa korzyść DECIMAL(5,0)typu danych dla liczb całkowitych?

vstrien
źródło
1
Jedną korzyścią może być pięciocyfrowy limit. Ale zastanawiam się, ile miejsca można zaoszczędzić przy takiej zmianie.
dezso,
3
IMO, jeśli musisz tylko upewnić się, że wartości kolumn mieszczą się w zakresie, użyj ograniczenia sprawdzania. Myślę, że jedyną kwestią, którą należy wziąć pod uwagę, jest możliwość, że ta kolumna będzie wymagać wartości ułamkowych w przyszłości.
Jon Seigel
3
Jeśli martwią się o miejsce do przechowywania, lepiej nadają się do kompresji niż to. Nie ma wymiernej korzyści z używania liczb dziesiętnych (x, 0) zamiast int / bigint.
Robert L. Davis,
7
Kolejna różnica między decimal(x,0)typem całkowitym a liczbą całkowitą pokazuje się w podziale arytmetycznym. Jeśli podzielisz liczbę całkowitą przez liczbę całkowitą, otrzymasz liczbę całkowitą. Dzieląc liczbę dziesiętną (x, 0) przez liczbę całkowitą, otrzymujesz liczbę dziesiętną (x + 6,6).
Andriy M
@AndriyM, myślę, że to największa korzyść. Przeredaguj to w odpowiedź zamiast komentarza, a ja oznaczę to jako odpowiedź.
vstrien

Odpowiedzi:

8

Zgadzam się, że nie ma żadnych rzeczywistych korzyści w zakresie miejsca do przechowywania, o ile porównujesz DECIMAL (9, 0) vs INT lub DECIMAL (18, 0) vs BIGINT. (W obrębie jednego bajtu.)

Jeśli chodzi o przetwarzanie, jak @Andriy mówi, że DECIMAL naturalnie podzieli się na typ, który nie traci części ułamkowej, jeśli jest to dla Ciebie ważne.

Z drugiej strony praca z rodzimymi typami INT jest znacznie szybsza z liczbowego punktu widzenia, jeśli wykonujesz dużo SUM (s) lub porównań (takich jak wyszukiwanie wartości), ponieważ są one wydajniej przetwarzane przez procesor. Porównanie int to dwa kody asemblacyjne (MOV, CMP), ale każde porównanie dziesiętne będzie o wiele, wiele więcej.

Chris Chubb
źródło
Twoja odpowiedź ma sens, ale procesor nie ma żadnej wiedzy na temat typów danych. Tak więc jeden typ danych 4 bajtów jest porównywany tak szybko, jak inny typ danych 4 bajtów. Czy możesz wykazać (na przykład, powtarzalnym testem wydajności), że istnieje wydajność w użyciu DECIMAL(9, 0)zamiast INT?
vstrien
2
Myślałem, że mogę, ale przyznam, że moje testy nie przyniosły jednoznacznych wyników. Być może SQL robi optymalizację, aby zredukować problem do matematyki liczb całkowitych. Mój testbed: `- Porównanie porównania SET @StartTime = SYSDATETIME () WHILE (@CounterINT <@SizeINT) SET @CounterINT = @CounterINT + 1 PRINT 'INT wziąć' + CONVERT (VARCHAR (20), DATEDIFF (milisekunda, @StartTime , SYSDATETIME ())) + 'milliseconds' --Decimal SET @StartTime = SYSDATETIME () WHILE (@CounterDEC <@SizeDEC) SET @CounterDEC = @CounterDEC + 1 PRINT 'DEC wziął' + CONVERT (VARCHAR (20), DATEDIFF (millisecond, @StartTime, SYSDATETIME ())) + 'milliseconds' '
Chris Chubb
Myślę, że SQL Server rzeczywiście tam coś optymalizuje. Pomimo optymalizacji DECIMALnadal trwa zwykle nieco dłużej (przynajmniej w moim systemie programistycznym). W serii 10 testów około 51 ms DEC vs. 46 ms INT.
vstrien
2

Wygląda na to, że nie będzie żadnych korzyści w zakresie miejsca do przechowywania.

Jeśli klient obawia się, że twoje wartości będą większe niż 2 ^ 32-1 (maksymalna liczba całkowita dodatnia może przechowywać), powinieneś rozważyć przejście do BigInt - z 64 bitami ( 8 bajtów) .

AlexTheDeveloper
źródło