SQL Server Ondalık (9, 0) ve INT


15

Müşterilerimizden biri DECIMAL(18,0)SQL Server 2008R2 veritabanındaki bazı veri sütunlarını kullanır . Sütunlar oldukça yavaş büyüdüğü için, yakın zamanda bir DECIMAL(5,0)miktar depolamayı yeniden kazanmak için veri türünü değiştirmeyi önerdi .

MSDN kitaplığına göre , DECIMAL(5,0)veri tipinin depolama alanı , tıpkı veri tipi gibi DECIMAL(9,0), 5 bayttır. INT1 bayt daha küçüktür, ancak her şeyi saklayabilen -99,999 ila 99,999 yerine -2 ^ 31 ila 2 ^ 31 aralığında DECIMAL(5,0)saklayabilir. DECIMAL5 bayta ( DECIMAL(9,0)) uyan en büyükler bile yalnızca -999,999,999 ila 999,999,999 aralığındaki ( INT4 baytlık aralık tekliflerinin yarısından daha az) tamsayıları depolayabilir .

Ben DECIMALüzerinde kullanarak iki "faydaları" düşünebilirsiniz INT:

  • Daha fazla depolama alanı kullanmadan ölçek ekleyebilme
  • Veri türünü değiştirmeden hassasiyeti 38 basamağa kadar ölçeklendirme yeteneği

ama bunlar benim görüşüme göre gerçek faydalar değil:

  • Tamsayılara ölçek eklemek çok az durumda mantıklıdır (ölçeğin fark yarattığı çoğu durumda, önceden de eklenebilir)
  • SQL Server her kesinlik / ölçek kombinasyonunu farklı bir veri türü olarak görür, bu nedenle kesinlik veya ölçek artırılırken veri türü tek başına bırakılmaz.

Bu beni meraklandırıyor: DECIMAL(5,0)Tamsayılar için bir veri tipinin ek yararı nedir?


1
Bir fayda beş basamaklı sınır olabilir. Ama böyle bir değişiklikle ne kadar depolama alanı ayırabileceğinizi merak ediyorum.
dezso

3
IMO, yalnızca sütun değerlerinin bir aralık içinde olduğundan emin olmanız gerekiyorsa, bir kontrol kısıtlaması kullanın. Bence buradaki tek düşünce, bu sütunun gelecekte kesirli değerler gerektirme olasılığı varsa olurdu.
Jon Seigel

3
Depolama alanı konusunda endişe duyuyorlarsa, sıkıştırma kullanmaktan daha uygundurlar. İnt / bigint yerine ondalık (x, 0) kullanmanın somut bir faydası yoktur.
Robert L Davis

7
decimal(x,0)Tam sayı tipi ile tamsayı arasındaki bir fark da aritmetik bölünmede kendini gösterir. Bir int'i int ile böldüğünüzde int alırsınız. Ondalık (x, 0) değerini int ile böldüğünüzde, ondalık (x + 6,6) elde edersiniz.
Andriy M

@AndriyM, bence bu en büyük fayda. Bir yorum yerine bir cevaba dönüştürün ve cevap olarak işaretleyeceğim.
vstrien

Yanıtlar:


8

DECIMAL (9, 0) ile INT veya DECIMAL (18, 0) ile BIGINT arasında karşılaştırma yaptığınız sürece depolama alanı açısından gerçek bir fayda olmadığını kabul ediyorum . (Tek bir bayt içinde.)

İşleme açısından, @Andriy'nin dediği gibi, DECIMAL sizin için önemliyse doğal olarak kesirli kısmı kaybetmeyen bir türe bölünecektir.

Öte yandan, CPU tarafından daha verimli bir şekilde oluşturuldukları için çok sayıda SUM () veya karşılaştırma (değerlerde arama yapmak gibi) yapıyorsanız , yerel INT türleriyle çalışmak sayısal bir bakış açısından çok daha hızlıdır. Bir int karşılaştırma iki montaj opodudur (MOV, CMP), ancak herhangi bir ondalık karşılaştırma çok daha fazla olacaktır.


Cevabınız mantıklı, ancak bir işlemcinin veri türleri hakkında bilgisi yok. Böylece 4 baytlık bir veri türü, 4 baytlık başka bir veri türü kadar hızlı karşılaştırılır. Örneğin tekrarlanabilir bir performans testiyle) DECIMAL(9, 0)yerine bir performans isabeti olduğunu gösterebilir misiniz INT?
vstrien

2
Yapabileceğimi düşündüm, ancak testlerimin sonuçsuz olduğunu kabul edeceğim. Belki de SQL problemi tamsayı matematiğe indirgemek için bir optimizasyon yapıyor. Test yatağım: `--Int karşılaştırma SET @StartTime = SYSDATETIME () WHILE (@CounterINT <@SizeINT) SET @CounterINT = @CounterINT + 1 PRINT 'INT' + CONVERT (VARCHAR (20), DATEDIFF (milisaniye, @StartTime) aldı , SYSDATETIME ())) + 'milisaniye' --Decimal SET @StartTime = SYSDATETIME () WHILE (@CounterDEC <@SizeDEC) SET @CounterDEC = @CounterDEC + 1 PRINT 'DEC' + CONVERT (VARCHAR (20), DATEDIFF (milisaniye, @StartTime, SYSDATETIME ())) + 'milisaniye' '
Chris Chubb

SQL Server orada bir şey gerçekten optimize düşünüyorum. Optimizasyona rağmen DECIMALhala biraz daha uzun sürüyor (en azından geliştirme sistemimde). 10 msn çalışmasında 51 ms DEC ve 46 ms INT.
vstrien

2

Depolama alanı açısından hiçbir faydası olmayacak gibi görünüyor .

İstemci değerlerin olacağı endişeleri varsa 2'den büyük ^ 32-1 (maksimum pozitif değer tamsayı saklayabilirsiniz) o zaman hareket düşünmelisiniz BigInt - ile 64 bit (olan 8 bayt) .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.